我不明白为什么这段代码有效:
class Base {
public:
virtual void doStuff() const{}
Base(Base & b) = delete;
Base() {
cout << "Base" << endl;
}
~Base() {
cout << "~Base" << endl;
}
friend ostream& operator<<(ostream& out, const Base& a) {
return out << "me";
}
};
int main(){
unique_ptr<Base> pt = make_unique<Base>();
auto npt = move(pt);
auto &a = *pt;
if (pt == nullptr)
cout << "yes nullptr" << endl;
cout << a << endl;
}
Visual Studio 2015中的输出是:
Base
yes nullptr
me
~Base
所以它不会崩溃,pt
在移动后甚至可以使用。
在coliru在线编译器中,它在第cout << a << endl;
行崩溃。我不明白它是如何在第auto &a = *pt;
行崩溃的,因为此时pt等于nullptr而命令auto &refToNull= nullptr;
是编译错误。
我将理解有关正在发生的事情的澄清。
答案 0 :(得分:1)
首先,声明
auto &a = *pt;
是未定义行为,未定义。在C ++中取消引用nullptr
不会使崩溃您的程序,它可能会发生一切。
您可能希望从代码中获得segmentation fault,但不会发生这种情况,因为您实际上无法访问对象a
。
的确,您的operator<<
会占用Base
个对象,但根本不会使用它。
相反,如果您尝试执行以下操作:
friend ostream& operator<<(ostream& out, const Base& a) {
a.do_stuff();
}
您的程序将被操作系统杀死,因为错误的内存(实际上是0x0内存)引用了a
对象。
有关nullptr derefereing的相关问题是Here。
答案 1 :(得分:0)
auto npt = move(pt);
将pt
的所有权转移到npt
,pt
一个nullptr
。由于pt
现在是nullptr
,因此if (pt == nullptr) cout << "yes nullptr" << endl;
正确输出“yes nullptr”。
auto &a = *pt;
表示您尝试取消引用nullptr
这只是未定义的行为。 cout << a << endl;
可能会导致任何可能发生的事情,但不一定会导致程序崩溃。