例如,如果您有声明std::unique_ptr<A> a;
,那么以下会导致问题吗?
a->foo(std::move(a));
Run Code Online (Sandbox Code Playgroud)
在我的例子中,foo
是一个虚函数,所以我不能把它移出课堂.如果上面的代码结果导致问题,那么有什么方法可以产生相同的效果呢?
C++ 11和C++ 14
这取决于签名foo
:
foo(std::unique_ptr<A> &&)
,则调用是安全的,因为指针保留旧值直到foo
开始执行.是否foo
更改指针是不相关的,因为在评估命名函数的表达式之后,来自被调用函数执行的任何语句都会被排序.foo(std::unique_ptr<A>)
,则调用具有未定义的行为.虽然有一个规则,在计算运算符的结果之前计算运算符的操作数(所以你必须先进行评估a
才能知道foo
要调用哪个,因此调用它),这在这里是不够的,因为没有规则说函数参数在函数名称表达式之后排序.因此,a
可能已被移动,并且调用a.operator ->()
包含尝试取消引用空指针.C++ 17
从C++ 17开始,它是安全的.添加了几个新的排序规则,其中一个准确地解决了这个问题:
在函数调用表达式中,在每个参数表达式和每个默认参数之前对命名函数的表达式进行排序.
啊,好吧,我应该为17 C++之前发布一个安全版本.这很简单,只需自己添加必要的顺序,例如使用两个语句:
auto aRaw = a.get();
aRaw->foo(std::move(a));
Run Code Online (Sandbox Code Playgroud)