关于C ++中异常的最佳实践似乎是 抛出值,引用捕获。我查看了<exception>
和cppreference,发现std::exception
有一个拷贝构造函数但没有移动构造函数,这是为什么呢?拥有移动构造函数难道不会允许捕获值并因此简化指南吗?
关于C ++中异常的最佳实践似乎是 抛出值,引用捕获。我查看了<exception>
和cppreference,发现std::exception
有一个拷贝构造函数但没有移动构造函数,这是为什么呢?拥有移动构造函数难道不会允许捕获值并因此简化指南吗?
std::exception
的后代拥有数据。例如,std::runtime_error
拥有其 what()
消息。该消息是动态分配的,因为它可以是任意长度的消息。
然而,复制构造函数被标记为 noexcept
(隐式),因为 std::exception
的复制构造函数是 noexcept
的。
#include <stdexcept>
#include <type_traits>
int
main()
{
static_assert(std::is_nothrow_copy_constructible<std::runtime_error>{});
}
#include <exception>
#include <iostream>
#include <stdexcept>
int
main()
{
try
{
throw std::runtime_error("my message");
}
catch (std::exception e)
{
std::cout << e.what() << '\n';
}
}
输出结果(对我来说):
std::exception
我检查了几个编译器,显然try/catch
机制不使用移动语义。
#include <iostream>
using namespace std;
struct err {
err() { cout << "created err" << endl; }
err(const err&) { cout << "copied err" << endl; } // Compilation error if this is commented out
err(err&&) noexcept { cout << "moved err" << endl; }
~err() { cout << "destroyed err" << endl; }
};
void foo() {
throw err{};
}
int main() {
try {
cout << "calling foo" << endl;
foo();
cout << "called foo" << endl;
}
catch (err e) {
cout << "caught err" << endl;
}
}
输出:
调用foo
创建错误
复制错误
捕获错误
销毁错误
销毁错误
因此,拥有移动构造函数是无意义的。
为什么会这样可能是另一个问题的事情 :)