将 unique_ptr 分配给引用时,析构函数在成员函数之前被调用
Destructor gets called before member function when assigning unique_ptr to a reference
我正在使用 unique_ptr,但我得到了一些奇怪的结果。这是代码:
class Sniffer
{
public:
Sniffer()
{
cout << "Sniffer()" << endl;
s = "String!";
}
void operator()()
{
cout << "operator()(): " << s << endl;
}
~Sniffer()
{
cout << "~Sniffer()" << endl;
}
private:
string s;
};
int main()
{
cout << "Begin scope!" << endl;
{
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer()); // 1
//std::unique_ptr<Sniffer> p(new Sniffer()); // 2
//Sniffer& h = *p; // 2
h();
}
cout << "End scope!" << endl;
return 0;
}
我不明白为什么对于代码“1”,析构函数在 operator()() 之前被调用,而 "End Scope!" 根本没有被打印出来。代码没有崩溃,它执行到最后一行,我得到的输出是:
Begin scope!
Sniffer()
~Sniffer()
operator()(): Press any key to continue . . .
另一方面,代码“2”的行为符合预期:
Begin scope!
Sniffer()
operator()(): String!
~Sniffer()
End scope!
Press any key to continue . . .
我使用参考的原因只是因为我觉得 h()
比 (*p)()
或 p->operator()()
感觉更自然。谢谢。
因为当你这样做时
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer());
您创建的 std::unique_ptr
对象是 临时的 并且已被破坏,留下对不再存在的对象的引用,您进入了 undefined behavior.
当你这样做时
std::unique_ptr<Sniffer> p(new Sniffer());
您创建了一个实际的非临时对象 p
,您当然可以在其生命周期内对其进行引用。
行 1
创建了一个临时的 unique_ptr 对象,该对象被解除引用,其结果是引用 h
将指向的对象。但是,由于 unique_ptr 对象是临时对象,其析构函数将在分号处调用(请参阅 object lifetime)。这也将调用临时 unique_ptr 指向的 Sniffer
对象的析构函数。
代码 2
确实是您应该如何使用 unique_ptr。或者更好地使用 C++14 的 make_unique
.
unique_ptr 的全部目的是当 unique_ptr 对象超出范围时,它指向的任何内容都将自动销毁(或由自定义删除器删除)。在行 1
中,它甚至在您使用其内容之前就超出了范围。见 documentation:
std::unique_ptr is a smart pointer that retains sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope.
std::unique_pointer<Sniffer>
是你的“1”中的一个临时变量,因此在语句完成后被销毁。它的析构函数在到达下一个语句 (h();
) 之前销毁 Sniffer
对象。 h
是悬垂引用,因此 h()
(即 h.operator()()
)的结果未定义。
在你的例子“2”中,对象 p
继续存在直到包含范围的末尾,即在语句 h();
之后
在此声明中
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer());
创建了一个 std::unique_ptr<Sniffer>
类型的临时对象,该对象在语句执行结束时销毁。
因此引用 h
在代码块的范围内无效。
在此声明中
std::unique_ptr<Sniffer> p(new Sniffer()); // 2
对象 p 被创建并且将一直存在到代码块结束。所以参考h
Sniffer& h = *p;
在此范围内有效。
我正在使用 unique_ptr,但我得到了一些奇怪的结果。这是代码:
class Sniffer
{
public:
Sniffer()
{
cout << "Sniffer()" << endl;
s = "String!";
}
void operator()()
{
cout << "operator()(): " << s << endl;
}
~Sniffer()
{
cout << "~Sniffer()" << endl;
}
private:
string s;
};
int main()
{
cout << "Begin scope!" << endl;
{
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer()); // 1
//std::unique_ptr<Sniffer> p(new Sniffer()); // 2
//Sniffer& h = *p; // 2
h();
}
cout << "End scope!" << endl;
return 0;
}
我不明白为什么对于代码“1”,析构函数在 operator()() 之前被调用,而 "End Scope!" 根本没有被打印出来。代码没有崩溃,它执行到最后一行,我得到的输出是:
Begin scope!
Sniffer()
~Sniffer()
operator()(): Press any key to continue . . .
另一方面,代码“2”的行为符合预期:
Begin scope!
Sniffer()
operator()(): String!
~Sniffer()
End scope!
Press any key to continue . . .
我使用参考的原因只是因为我觉得 h()
比 (*p)()
或 p->operator()()
感觉更自然。谢谢。
因为当你这样做时
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer());
您创建的 std::unique_ptr
对象是 临时的 并且已被破坏,留下对不再存在的对象的引用,您进入了 undefined behavior.
当你这样做时
std::unique_ptr<Sniffer> p(new Sniffer());
您创建了一个实际的非临时对象 p
,您当然可以在其生命周期内对其进行引用。
行 1
创建了一个临时的 unique_ptr 对象,该对象被解除引用,其结果是引用 h
将指向的对象。但是,由于 unique_ptr 对象是临时对象,其析构函数将在分号处调用(请参阅 object lifetime)。这也将调用临时 unique_ptr 指向的 Sniffer
对象的析构函数。
代码 2
确实是您应该如何使用 unique_ptr。或者更好地使用 C++14 的 make_unique
.
unique_ptr 的全部目的是当 unique_ptr 对象超出范围时,它指向的任何内容都将自动销毁(或由自定义删除器删除)。在行 1
中,它甚至在您使用其内容之前就超出了范围。见 documentation:
std::unique_ptr is a smart pointer that retains sole ownership of an object through a pointer and destroys that object when the unique_ptr goes out of scope.
std::unique_pointer<Sniffer>
是你的“1”中的一个临时变量,因此在语句完成后被销毁。它的析构函数在到达下一个语句 (h();
) 之前销毁 Sniffer
对象。 h
是悬垂引用,因此 h()
(即 h.operator()()
)的结果未定义。
在你的例子“2”中,对象 p
继续存在直到包含范围的末尾,即在语句 h();
在此声明中
Sniffer& h = *std::unique_ptr<Sniffer>(new Sniffer());
创建了一个 std::unique_ptr<Sniffer>
类型的临时对象,该对象在语句执行结束时销毁。
因此引用 h
在代码块的范围内无效。
在此声明中
std::unique_ptr<Sniffer> p(new Sniffer()); // 2
对象 p 被创建并且将一直存在到代码块结束。所以参考h
Sniffer& h = *p;
在此范围内有效。