我有一个Foo课 - 没什么特别的。另一个类的方法是将unique_ptr返回给Foo。在我的头撞到我的显示器一天后,我把问题减少到以下几点:
std::unique_ptr<Foo> Other::method(float arg) {
Foo *ptr = new Foo(arg);
std::unique_ptr<Foo> result;
result.reset(ptr);
.....
return result; // option 1 - does not work
return std::move(result); // option 2 would work
}
如果选项2返回被注释掉并使用CLang&amp; Mac上的LLDB我发现只要调用reset方法,结果就会开始认为它拥有一个nullptr。当结果的定义简化为单行时,会出现同样的问题:
std::unique_ptr<Foo> result(new Foo(arg));
调试器显示一旦执行退出Foo构造函数,结果保存的内部指针就变为nullptr。
另一方面,一旦我注释掉return语句的选项1并用选项2替换它,事情开始显示合理的行为。尽管在初始化和返回之间存在许多代码行。
这一切都非常令人惊讶。特别是考虑到类似的代码在另一种情况下工作而不使用std :: move()。 CLang是在玩一些优化游戏而且有错误或我不明白?
我相信这个问题与previously asked one不同。上一个问题询问返回语句将调用哪种构造函数的复制或移动,以及为什么代码在没有显式移动的情况下无法编译。另一方面,我指出两个版本都应该工作,c ++ 11编译器应该弄清楚自己使用移动构造函数。更糟糕的是,在这种情况下,CLang会过早地使用NRVO,从而使unique_ptr初始化和违规返回语句之间的几十行代码无效(即使在调试版本中也是如此)。而不是编译器玩这样的游戏,我更喜欢它只是在没有显式调用std :: move()的情况下拒绝编译。这样可以省去无数个小时寻找问题。