在std :: unique_ptr超出范围后仍可访问对象.不同的运行时行为

Dra*_*ake 1 c++ unique-ptr c++11 dangling-pointer

下面的代码向函数传递modify_entry一个指向类型对象的指针,Entry并在函数体内部unique_ptr采用原始指针.但是,指针指向的对象似乎在函数返回后仍然存在.

当我编译这段代码

#include <iostream>
#include <memory>

struct Entry {

    Entry(std::string name) : name_(name) { std::cout << "Constructor for " + name_ + '\n'; }
    ~Entry() { std::cout << "Destructor for " + name_ + '\n'; }
    std::string name_;

};

void modify_entry(Entry* e_ptr){

    std::cout << "Inside modify_entry()\n";
    std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";

}

int main(int argc, const char * argv[])
{

    Entry* entry_ptr = new Entry("John");
    modify_entry(entry_ptr);
    std::cout << "Back from modify_entry()\n";
    std::cout << entry_ptr->name_ << '\n';      // <---- line 25

    return 0;

}
Run Code Online (Sandbox Code Playgroud)

同

clang 3.4版(标签/ RELEASE_34/final)

目标:x86_64-apple-darwin13.1.0

线程模型:posix

它运行没有错误,输出是

约翰的构造函数

里面的modify_entry()

John Doe的析构函数

从modify_entry()返回

约翰·多伊

在这里,但是,我得到的,因为第25行的运行时错误.

问:运行clang生成的可执行文件时,为什么没有运行时错误?

如果有人能澄清情况,我将非常感激.请注意,我并未尝试正确转让所有权.这个人为设计的坏代码示例是调试过程的副产品.make_unique移动语义unique_ptr等等都很棒,但这不是我要问的.

提前致谢.

R. *_*des 6

问:运行clang生成的可执行文件时,为什么没有运行时错误?

因为未定义的行为未定义.程序在其生命周期结束后尝试访问该对象.C++没有为这些程序定义任何行为.

make_unique并且移动语义unique_ptr等很好,这样的事情只是你应该使用它们的另一个原因.


Vau*_*ato 6

但是,指针指向的对象似乎在函数返回后仍然存在.

这里的关键是"似乎".实际上,这一Entry生命终结于这一行的结尾:

 std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";
Run Code Online (Sandbox Code Playgroud)

在unique_ptr采取了内存的所有权,但临时unique_ptr的一生在该声明的结尾处结束,所以它也删除Entry它拥有.访问以前由对象使用的内存是未定义的行为.它适用于某些平台而非其他平台只是未定义行为的本质.