Is there any situation in which an object's storage might change during its lifetime?

前端 未结 3 789
我寻月下人不归
我寻月下人不归 2021-01-11 09:42

I\'ve always assumed that an object begins and ends its lifetime in the same memory location, but I\'ve recently come across a scenario where I need to be sure. Specifically

相关标签:
3条回答
  • 2021-01-11 10:11

    Specifically, I'm looking for a guarantee from the standard that no matter what optimizations the compiler performs the address an object is constructed at is the same one that it will have its destructor called from...

    and that its destructor is, indeed, guaranteed to be called from that location unless the program is terminating.

    The standard guarantees both for automatic variables and static variables as long as one doesn't do bad things with the objects. However, it does not guarantee either for objects allocated from the free store.

    Even for automatic variables, a crafty programmer can subvert the intention through pointer manipulation and explicitly calling the destructor through a pointer.

    In addition, the wrong destructor will be called when delete-ing a base class pointer when the base class does not have a virtual destructor. This will be a programming error, not the result of intention to subvert.

    Example:

    struct Base
    {
       int b;
    };
    
    struct Derived : virtual Base
    {
       float d;
    };
    
    
    int main()
    {
       {
          Derived d1; // Not a problem.
       }
    
       {
          Derived d1;
          Derived* ptr = &d1;
          delete ptr;    // Bad. The programmer subverts the program.
                         // Must not use delete.
       }
    
       {
          Derived* d2 = new Derived; // The destructor does not get called automatically.
       }
    
       {
          Derived* d2 = new Derived;
          delete d2;   // OK. The proper destructor gets called.
       }
    
       {
          Derived* d2 = new Derived;
          Base* ptr = d2;
          delete ptr;  // Programmer error. The wrong destructor gets called.
       }
    }
    
    0 讨论(0)
  • 2021-01-11 10:13

    As mentioned by Nathan Oliver, the standard states that:

    [...] An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).

    Compilers respect this, and there are objects (similar to the one you describe) for which it must hold true. Consider std::mutex. A mutex cannot be copied or moved, and the reason for this is that it must remain at the same location in memory for the duration of it's lifetime in order to work.

    So how does copy/move elision work?

    Copy/move elision works by creating the object where it needs to go. It's that simple.

    We can see this behavior for ourselves:

    #include <iostream>
    
    struct Foo {
        Foo() {
            std::cout << "I am at " << (void*)this << '\n';
        }
        // Delete copy and move, to ensure it cannot be moved
        Foo(const Foo&) = delete;
        Foo(Foo&&) = delete;
    };
    
    Foo getFoo() {
        return Foo(); 
    }
    
    int main() {
    
        Foo* ptr = new Foo(getFoo()); 
    
        std::cout << "Foo ptr is at " << (void*)ptr << '\n';
        delete ptr; 
    }
    

    This code outputs:

    I am at 0x201ee70
    Foo ptr is at 0x201ee70
    

    And we see that Foo remains at the same location for the duration of it's lifetime, without ever being copied or moved, even though it's being created in dynamically allocated memory.

    How does the compiler know where to create an object?

    If a function returns a type that is not trivially copyable, then that function takes an implicit parameter representing the memory address where it's supposed to construct the return value.

    0 讨论(0)
  • 2021-01-11 10:16

    What you are looking for is defined in [intro.object]/1

    [...] An object occupies a region of storage in its period of construction ([class.cdtor]), throughout its lifetime, and in its period of destruction ([class.cdtor]).

    This means the address cannot change as long as you can access it.

    0 讨论(0)
提交回复
热议问题