为什么指针即使在分配给它的unique_ptr超出范围后仍然存在



我最近开始学习C++中的智能指针和移动语义。但我不明白为什么这个代码有效。我有这样的代码:

#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test() 
{
cout << "Object created" << endl;
}
void testMethod()
{
cout << "Object existing" << endl;
}
~Test() 
{
cout << "Object destroyed" << endl;
}
};
int main(int argc, char *argv[])
{
Test* testPtr = new Test{};
{
unique_ptr<Test> testSmartPtr(testPtr);
}
testPtr->testMethod();

return 0;
}

我的输出是:

Object created
Object destroyed
Object existing

为什么行testPtr->testMethod()工作?如果指针是左值,unique_ptr不会删除销毁时分配给它的指针吗?

编辑:我从评论中了解到,这个方法不检查指针是否存在。如果是,有没有办法检查指针是否有效?

编辑:我学会了不应该用无效指针做任何事情。感谢您的回答和评论。

编辑:即使这个代码工作:

#include <iostream>
#include <memory>
using namespace std;
class Test
{
public:
Test(int num) :
number{ num }
{
cout << "Object created" << endl;
}
void testMethod(int valueToAdd)
{
number += valueToAdd;
cout << "Object current value: " << number << endl;
}
~Test() 
{
cout << "Object destroyed" << endl;
}
private:
int number;
};
int main(int argc, char *argv[])
{
Test* testPtr = new Test(42);
{
unique_ptr<Test> testSmartPtr(testPtr);
}
testPtr->testMethod(3);

return 0;
}

我想这是因为编译器优化了它。无论如何,我真的不应该对无效指针做任何事情。

您不需要std::unique_ptr来编写具有相同问题的代码

int main(int argc, char *argv[])
{
Test* testPtr = new Test{};
delete testPtr;
testPtr->testMethod();       // UNDEFINED !!!
return 0;
}

这里的输出与您的相同https://godbolt.org/z/8bocKGj1M,但它可能完全是另一回事。该代码具有未定义的行为。不能取消引用无效的指针。

如果您在testMethod()中实际使用了对象的成员,则更有可能出现错误输出或崩溃,但也不能保证。看起来很好是未定义行为的最糟糕体现。

您的代码很好地说明了为什么应该完全禁止原始new。至少您应该只将new作为智能指针构造函数的参数来调用,或者更好的是,使用std::make_unique。它基本上只是通过new对构造函数调用的包装,它的主要目的是让您编写不含new:的代码

int main(int argc, char *argv[])
{
auto testPtr = std::make_unique<Test>();
testPtr->testMethod();    
return 0;
}

即使这样,你也可以访问原始指针并做错误的事情。聪明的指针有助于提高所有权,但它们并不是傻瓜式的。

相关内容

  • 没有找到相关文章

最新更新