2017-07-30 112 views
0

后,我不明白为什么这个代码工作:使用的unique_ptr移动

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;是编译错误。

我将不胜感激关于发生了什么的澄清。

+4

未定义的行为未定义。 – songyuanyao

+0

你忘记你的'operator <<'函数是*不是成员函数*。这是一个全球性的非会员功能。尝试调用一个实际的成员函数,或者改为访问一个成员变量。 –

+2

_So它不会粉碎,'pt'在被移出后甚至可以使用。谁说它应该总是崩溃?这是未定义的行为。 –

回答

0

auto npt = move(pt);pt的所有权转让给npt离开pt a nullptr。由于pt现在是nullptr,因此if (pt == nullptr) cout << "yes nullptr" << endl;正确输出“yes nullptr”。

auto &a = *pt;表示您试图取消引用nullptr这只是一个未定义的行为cout << a << endl;可能导致任何事情都可能发生但不一定会崩溃的程序。

1

首先,声明

auto &a = *pt; 

未定义行为,一个没有被定义。在C++中取消引用nullptr并不会使崩溃您的程序,它可能发生一切。


什么你可能从你的代码期望是segmentation fault,而是因为你其实并不曾访问该对象a不会发生。

确实,您的operator<<需要一个Base对象,但它根本不使用它。

相反,如果你试图做这样的事情:

friend ostream& operator<<(ostream& out, const Base& a) { 
    a.do_stuff(); 
} 

你的方案将由操作系统,因为a对象是在一个错误的内存(实际为0x0内存)引用被杀死。

关于nullptr derefereing的相关问题是Here