std::unique_ptr超出范围后仍然可以访问的对象.不同的运行时行为
Object still accessible after std::unique_ptr goes out of scope. Differing runtime behaviours
以下代码将指向类型为Entry
的对象的指针传递给函数modify_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;
}
带有
clang版本3.4(标签/RERELEASE_34/final)
目标:x86_64-apple-darwin13.1.0
线程型号:posix
它运行时没有错误,输出为
John 的建造师
内部修改入口()
John Doe 的破坏者
从modify_entry()返回
John Doe
然而,在这里,由于第25行的原因,我得到了一个运行时错误。
Q:为什么运行clang生成的可执行文件时没有运行时错误?
如果有人能澄清情况,我将不胜感激。请注意,我并没有试图正确地转移所有权。这个错误代码的例子是调试过程的副产品。make_unique
和unique_ptr
的移动语义等都很棒,但这不是我想要的。
提前谢谢。
但是,指针指向的对象似乎在函数返回后仍然存在。
这里的关键是"似乎"。实际上,Entry
的寿命在这一行的末尾结束:
std::unique_ptr<Entry>{e_ptr}->name_ += " Doe";
unique_ptr
已经取得了内存的所有权,但临时unique_ptr
的生存期在该语句结束时结束,因此它也删除了它拥有的Entry
。访问对象以前使用的内存是未定义的行为。它在某些平台上有效,而在其他平台上无效,这正是未定义行为的本质。
Q: 为什么运行clang生成的可执行文件时没有运行时错误?
因为未定义的行为是未定义的。程序在对象的生存期结束后尝试访问该对象。C++没有为这样的程序定义任何行为。
make_unique
和unique_ptr
的移动语义等都很棒,像这样的东西只是你应该使用它们的另一个原因。
因为您正在执行的是未定义的行为,所以在main
函数中使用指向已销毁对象的指针时。
对象已被破坏(删除),但您仍然有一个指向所在位置的指针,取消引用该指针会导致未定义的行为。
- 按基类对象访问派生类资源时出错
- 使用基类对象访问派生的仅类方法
- 从 const 对象访问非 const 方法
- 如何在C++中使用类对象访问指针数据成员
- 如何通过不同的指针使用类的对象访问结构?(链表)(C++)
- 使用二进制搜索树中的迭代器对象访问左侧节点
- 为什么引用类型在使用临时对象访问时是左值
- 从父对象 c++ 访问子方法
- 无法通过指针或对象 c++ 访问受保护的成员
- 为什么可以从类中的对象访问类的私有变量
- 对类似"struct {double, int}"对象使用reinterpret_cast进行对象访问
- 通过无符号 char 别名进行对象访问,加载和存储时会发生什么?
- 从对象访问结构枚举
- 如何全局创建对象并使用该对象访问全局范围内的公共成员函数
- 在C 中,可以从第三个共享对象访问其他两个不同共享对象
- 如何在C 中提供一个可呼叫的对象访问,例如lambda
- C 向量对象访问
- C++是否可以从同级第二个派生对象访问第一个派生对象的受保护基础数据成员?
- 如何从类内实例化的对象访问私有变量
- 多态性:通过类文本或对象访问静态成员