Placement new and explicit destruction

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • REH

    Placement new and explicit destruction

    This curiosity popped into my head on the way to work today. I
    wouldn't actually do this, but just wondering. Is the following
    defined behavior?

    #include <new>

    class T { };

    int main()
    {
    T* p = new T();

    p->~T();
    new(p) T();

    delete p;

    return 0;
    }

  • Victor Bazarov

    #2
    Re: Placement new and explicit destruction

    REH wrote:
    This curiosity popped into my head on the way to work today. I
    wouldn't actually do this, but just wondering. Is the following
    defined behavior?
    >
    #include <new>
    >
    class T { };
    >
    int main()
    {
    T* p = new T();
    >
    p->~T();
    new(p) T();
    >
    delete p;
    >
    return 0;
    }
    Yes. It's the pattern some folks are using to "forward constructor
    calls". The functionality is so often asked for that the Committee
    is changing the language to allow forwarding constructors, BTW.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask


    Comment

    • REH

      #3
      Re: Placement new and explicit destruction

      On Jul 16, 5:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
      Yes. It's the pattern some folks are using to "forward constructor
      calls". The functionality is so often asked for that the Committee
      is changing the language to allow forwarding constructors, BTW.
      >
      Thanks for replying Victor. I'm not familiar with the term "forward
      constructor" and Google is no help. Could you please point me to some
      information (or even give a quick explanation)?

      Rich


      Comment

      • Victor Bazarov

        #4
        Re: Placement new and explicit destruction

        REH wrote:
        On Jul 16, 5:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
        >Yes. It's the pattern some folks are using to "forward constructor
        >calls". The functionality is so often asked for that the Committee
        >is changing the language to allow forwarding constructors, BTW.
        >>
        >
        Thanks for replying Victor. I'm not familiar with the term "forward
        constructor" and Google is no help. Could you please point me to some
        information (or even give a quick explanation)?
        Given the class

        class A {
        double d;
        public:
        A(double a) : d(a) { /* and something else important */}
        A(double const *pa, size_t i) : d(pa[i]) { /* again */ }
        };

        , had there been constructor forwarding, we could just do

        ...
        A(double const *pa, index i) : A(pa[i]) {}

        and it would call the former constructor (with a single 'double'
        argument).

        V
        --
        Please remove capital 'A's when replying by e-mail
        I do not respond to top-posted replies, please don't ask


        Comment

        • James Kanze

          #5
          Re: Placement new and explicit destruction

          On Jul 16, 11:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
          REH wrote:
          This curiosity popped into my head on the way to work today. I
          wouldn't actually do this, but just wondering. Is the following
          defined behavior?
          #include <new>
          class T { };
          int main()
          {
          T* p = new T();
          p->~T();
          new(p) T();
          delete p;
          return 0;
          }
          Yes. It's the pattern some folks are using to "forward constructor
          calls". The functionality is so often asked for that the Committee
          is changing the language to allow forwarding constructors, BTW.
          It's definitly legal, but I don't quite see what it has to do
          with forwarding constructors. If I've understood the proposals
          correctly, a forwarding constructor is where one constructor
          first calls another constructor to do the job, then does some
          additional processing. Here, the poster first allocates and
          constructs the object, then destructs it without deallocating
          (leaving raw memory), then reconstructs it in the raw memory.

          --
          James Kanze (GABI Software) email:james.kan ze@gmail.com
          Conseils en informatique orientée objet/
          Beratung in objektorientier ter Datenverarbeitu ng
          9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

          Comment

          • REH

            #6
            Re: Placement new and explicit destruction

            On Jul 17, 5:15 am, James Kanze <james.ka...@gm ail.comwrote:
            On Jul 16, 11:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
            >
            >
            >
            REH wrote:
            This curiosity popped into my head on the way to work today. I
            wouldn't actually do this, but just wondering. Is the following
            defined behavior?
            #include <new>
            class T { };
            int main()
            {
            T* p = new T();
            p->~T();
            new(p) T();
            delete p;
            return 0;
            }
            Yes. It's the pattern some folks are using to "forward constructor
            calls". The functionality is so often asked for that the Committee
            is changing the language to allow forwarding constructors, BTW.
            >
            It's definitly legal, but I don't quite see what it has to do
            with forwarding constructors. If I've understood the proposals
            correctly, a forwarding constructor is where one constructor
            first calls another constructor to do the job, then does some
            additional processing. Here, the poster first allocates and
            constructs the object, then destructs it without deallocating
            (leaving raw memory), then reconstructs it in the raw memory.
            >
            I don't want to speak for Victor, but what I think he was saying was
            that placement new can be used to simulate one constructor calling
            another. Thus:

            class foo {
            public:

            foo(int i);

            foo(double d);
            };

            foo::foo(double d)
            {
            new(this) foo(123);
            }


            Comment

            • Victor Bazarov

              #7
              Re: Placement new and explicit destruction

              REH wrote:
              On Jul 17, 5:15 am, James Kanze <james.ka...@gm ail.comwrote:
              >On Jul 16, 11:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.net>
              >wrote:
              >>
              >>
              >>
              >>REH wrote:
              >>>This curiosity popped into my head on the way to work today. I
              >>>wouldn't actually do this, but just wondering. Is the following
              >>>defined behavior?
              >>>#include <new>
              >>>class T { };
              >>>int main()
              >>>{
              >>> T* p = new T();
              >>> p->~T();
              >>> new(p) T();
              >>> delete p;
              >>> return 0;
              >>>}
              >>Yes. It's the pattern some folks are using to "forward constructor
              >>calls". The functionality is so often asked for that the Committee
              >>is changing the language to allow forwarding constructors, BTW.
              >>
              >It's definitly legal, but I don't quite see what it has to do
              >with forwarding constructors. If I've understood the proposals
              >correctly, a forwarding constructor is where one constructor
              >first calls another constructor to do the job, then does some
              >additional processing. Here, the poster first allocates and
              >constructs the object, then destructs it without deallocating
              >(leaving raw memory), then reconstructs it in the raw memory.
              >>
              >
              I don't want to speak for Victor, but what I think he was saying was
              that placement new can be used to simulate one constructor calling
              another. Thus:
              >
              class foo {
              public:
              >
              foo(int i);
              >
              foo(double d);
              };
              >
              foo::foo(double d)
              {
              new(this) foo(123);
              }
              You got it. I of course don't mean that the object should be
              constructed twice, so the latter c-tor needs to have the destruction
              in it too:

              foo::foo(double d)
              {
              this->~foo();
              new (this) foo(123);
              }

              V
              --
              Please remove capital 'A's when replying by e-mail
              I do not respond to top-posted replies, please don't ask


              Comment

              • James Kanze

                #8
                Re: Placement new and explicit destruction

                On Jul 17, 5:43 pm, REH <spamj...@stny. rr.comwrote:
                On Jul 17, 5:15 am, James Kanze <james.ka...@gm ail.comwrote:
                On Jul 16, 11:35 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:
                REH wrote:
                This curiosity popped into my head on the way to work today. I
                wouldn't actually do this, but just wondering. Is the following
                defined behavior?
                #include <new>
                class T { };
                int main()
                {
                T* p = new T();
                p->~T();
                new(p) T();
                delete p;
                return 0;
                }
                Yes. It's the pattern some folks are using to "forward constructor
                calls". The functionality is so often asked for that the Committee
                is changing the language to allow forwarding constructors, BTW.
                It's definitly legal, but I don't quite see what it has to do
                with forwarding constructors. If I've understood the proposals
                correctly, a forwarding constructor is where one constructor
                first calls another constructor to do the job, then does some
                additional processing. Here, the poster first allocates and
                constructs the object, then destructs it without deallocating
                (leaving raw memory), then reconstructs it in the raw memory.
                I don't want to speak for Victor, but what I think he was saying was
                that placement new can be used to simulate one constructor calling
                another.
                Except that it can't, in general.
                Thus:
                class foo {
                public:
                foo(int i);
                foo(double d);
                };
                foo::foo(double d)
                {
                new(this) foo(123);
                Which is undefined behavior if the class has a non-trivial
                destructor.
                }
                The reason why the standards committee is adding forwarding
                constructors is precisely because there is no way of simulating
                it in the current language.

                --
                James Kanze (GABI Software) email:james.kan ze@gmail.com
                Conseils en informatique orientée objet/
                Beratung in objektorientier ter Datenverarbeitu ng
                9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


                Comment

                • James Kanze

                  #9
                  Re: Placement new and explicit destruction

                  On Jul 17, 7:18 pm, "Victor Bazarov" <v.Abaza...@com Acast.netwrote:

                  [...]
                  You got it. I of course don't mean that the object should be
                  constructed twice, so the latter c-tor needs to have the destruction
                  in it too:
                  foo::foo(double d)
                  {
                  this->~foo();
                  new (this) foo(123);
                  }
                  That's technically also undefined behavior, since you are
                  calling the destructor on an object whose constructor hasn't yet
                  finished running. (In practice, of course, you know what's in
                  your class, and you'll have ensured that you've set up enough
                  for the destructor to run without problems before calling it.)

                  --
                  James Kanze (GABI Software) email:james.kan ze@gmail.com
                  Conseils en informatique orientée objet/
                  Beratung in objektorientier ter Datenverarbeitu ng
                  9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

                  Comment

                  Working...