考虑:
struct Boo {
Boo (std::string v) : src {v} {}
Boo (const Boo&) = delete;
Boo& operator= (const Boo&) = delete;
Boo (Boo&& b) : src {std::move (b.src)} {}
Boo& operator= (Boo&& b) {
if (this != &b) {
foo ();
src = std::move (b.src);
}
return *this;
}
void show () {
std::cout << "|" << src << "|" << std::endl;
}
void foo () {
throw 1;
}
std::string src {};
};
和用法:
int main(int argc, char** argv) {
Boo s {"Boo1"};
Boo p {"Boo2"};
try {
p = std::move (s); // (X)
}
catch (...) {}
s.show ();
p.show ();
return 0;
}
输出看起来像这样:
如果在移动赋值运算符
中调用foo()
|Boo1|
|Boo2|
如果未调用foo()
|Boo2|
|Boo1|
问题:
在移动赋值运算符中抛出异常时,s
会发生什么?它是否具有先前的内容,就像在行(X)中使用std::move()
之前一样,或者内容是否完全移动到b
(函数参数)?
为什么在两种情况下输出都显示内容仍在std::string
个对象中?
答案 0 :(得分:3)
当抛出异常时,正常执行立即停止,并且调用堆栈被展开。直到第一个有效catch
。对于您的情况,这意味着只要您throw
暂停继续执行foo
和分配运算符函数,程序就会转到catch
中的main
功能,换句话说,什么都不会改变对象。
移动std::string
对象会使源处于有效但 uspecified 状态。应该注意的是,移动通常通过交换源和目标来实现,这将解释您看到的行为。