我最近开始学习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;
}
即使这样,你也可以访问原始指针并做错误的事情。聪明的指针有助于提高所有权,但它们并不是傻瓜式的。