Hel*_*and 1 c++ ownership-semantics rvalue-reference unique-ptr c++14
我遇到了类似于以下(或多或少最小)示例的 C++ 代码。请考虑底部函数中标记的方法调用:
#include <memory>
static unsigned returnValue = 5;
void setReturnValue(unsigned u) { returnValue = u; }
class MyObject
{
public:
MyObject(unsigned uIN) : u(uIN) {}
~MyObject() { u = 42; }
void method(std::unique_ptr<MyObject> uniqPtrToObject)
{
// Do something fancy with this unique pointer now,
// which will consume the object and its data
setReturnValue(uniqPtrToObject->getValue());
}
unsigned getValue() { return u; }
private:
unsigned u; // Some relevant object data
};
std::unique_ptr<MyObject> GetUniqToObject(unsigned u)
{
// Get the object in a fancy way. For now, assume it has just been constructed.
return std::make_unique<MyObject>(u);
}
int main()
{
std::unique_ptr<MyObject> uniqPtrToObject = GetUniqToObject(0);
// ===================================================
// Oops!
uniqPtrToObject->method(std::move(uniqPtrToObject));
// ===================================================
return returnValue;
}
Run Code Online (Sandbox Code Playgroud)
在调用对象的方法之一时移开对象看起来真的很奇怪。
我已经在https://godbolt.org ( )上尝试了我的示例x64-86 gcc 12.2,并且程序0按“应该”返回。只是一些幸运的巧合吗?
我仍然想知道:
由于我还没有找到一个好的资源来开始研究这种情况,我希望您能提供一些建议,从哪里开始阅读或如何轻松地决定这种情况。
由于您将这个问题标记为 C++14,这意味着我们现在必须解决哪个表达式首先解析的问题:uniqPtrToObject->函数参数的一个还是初始化?答案是……不确定。在 C++14 中,两者都不在另一个之前排序。在 C++17 中,是->在函数调用及其参数计算之前排序的,但这是一个显式更改。
这意味着在 C++14 中,代码的行为实际上是未定义的。如果参数的初始化unique_ptr发生在评估->表达式之前,则在评估时uniqPtrToObject将被移走。->因此,->获取 nullptr 并且您可以访问 nullptr 的状态。
现在,有一些评估顺序。但您不知道它是什么,编译器不需要告诉您,甚至不需要从一次执行到下一次执行保持一致。所以它是不可靠的。
假设我们正在谈论 C++17。这使得您的代码定义良好,因为它确保uniqPtrToObject->首先对其进行评估。
但是,即使您的代码“有效”,它在本示例的上下文中几乎肯定是无用的。原因是您uniqPtrToObject按值传递。这意味着method()将销毁,unique_ptr进而销毁它所拥有的对象。因此,如果对象在内部存储了一些数据,那么该数据现在就会丢失。该对象所做的任何修改都不再可访问,除非它存储在对象所有权范围之外的状态。
因此,即使在具有一致定义行为的 C++ 版本上,实际执行也不是一个好主意。
| 归档时间: |
|
| 查看次数: |
158 次 |
| 最近记录: |