移动赋值运算符异常
Exception in move assignment operator
考虑:
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
个对象中?
当抛出异常时,正常执行立即停止,调用堆栈展开。直到第一个有效的catch
。对于您的情况,这意味着一旦您 throw
继续执行 foo
和赋值运算符函数就会停止,并且程序会转到 main
中的 catch
函数,换句话说,不会发生任何会改变对象的事情。
移动 std::string
对象会使源处于有效但 未指定 状态。应该注意的是,移动通常通过 交换 源和目标来实现,这将解释您看到的行为。
考虑:
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
个对象中?
当抛出异常时,正常执行立即停止,调用堆栈展开。直到第一个有效的catch
。对于您的情况,这意味着一旦您 throw
继续执行 foo
和赋值运算符函数就会停止,并且程序会转到 main
中的 catch
函数,换句话说,不会发生任何会改变对象的事情。
移动 std::string
对象会使源处于有效但 未指定 状态。应该注意的是,移动通常通过 交换 源和目标来实现,这将解释您看到的行为。