【发布时间】:2015-04-20 07:58:17
【问题描述】:
我试图尽可能接近强异常保证,但是在玩std::move_if_noexcept 时,我遇到了一些看似奇怪的行为。
尽管下面的类中的移动赋值操作符被标记为noexcept,复制赋值操作符在调用时被调用,返回值为有问题的函数。
struct A {
A () { /* ... */ }
A (A const&) { /* ... */ }
A& operator= (A const&) noexcept { log ("copy-assign"); return *this; }
A& operator= (A&&) noexcept { log ("move-assign"); return *this; }
static void log (char const * msg) {
std::cerr << msg << "\n";
}
};
int main () {
A x, y;
x = std::move_if_noexcept (y); // prints "copy-assign"
}
问题
- 为什么之前的sn-p中没有调用move-assignment operator?
【问题讨论】:
-
这个问题是我的一个学生提出的,希望我能把最初的问题说得对(即使是通过这个极其简化的版本)。
-
所以这实际上是一个非常有趣的微妙之处,我非常感谢您的分析,但我认为您在回答中遗漏了一个有趣的例子。您正确地观察到
std::move_if_noexcept的行为似乎取决于移动构造而不是赋值,但在问题的提示中,您根本没有移动构造函数,更不用说noexcept一个,因为特殊函数生成规则。如果我添加一个,那么它确实会打印出“move-assign”。 (见:ideone.com/mvPe8b) -
虽然我不太喜欢假设,但我认为如果有人费心编写
noexcept移动构造函数,那么他们的移动赋值运算符也是noexcept是半合理的。所以,我希望std::move_if_noexcept在 99.9% 的时间里会做预期的事情。当然,我之前在行业中看到过 0.1% 的案例,所以,对这个发现赞不绝口! -
关于提交缺陷报告的第一步:goo.gl/Gj3oex。对许多背靠背的 cmets 感到抱歉。
-
@Mark:copy-constructor 有资格使对象 MoveConstructible,因为声明的函数没有标记为 noexcept
is_nothrow_move_constructible<T>::value == false;我会将其添加到答案中以使其清楚。