【发布时间】:2021-12-30 18:21:32
【问题描述】:
为什么在调用std::move(msg) 后msg 没有被修改?
int main()
{
std::string msg( "Error!" );
std::cout << "before try-catch: " << msg << '\n';
try
{
throw std::invalid_argument( std::move( msg ) );
}
catch ( const std::invalid_argument& ia )
{
std::cerr << ia.what( ) << '\n';
}
std::cout << "after try-catch: " << msg << '\n'; // Here I expect to see an empty msg
// like this: after try-catch:
return 0;
}
我想将 msg 移动到 std::invalid_argument 的 ctor 而不是复制它。我认为应该修改msg,并在调用std::move 后保持未指定但有效的状态。但是会发生这种情况:
before try-catch: Error!
Error!
after try-catch: Error!
为什么会这样? std::string 的 move ctor 没有被调用吗?还是尽管使用了 -O0 选项,但这是某种激进的编译器优化?
【问题讨论】:
-
std::invalid_argument有合适的构造函数吗? -
std::move只是对右值的强制转换,不保证调用移动构造函数std::invalid_argument( const std::string& );想要一个 const 引用,这里不执行构造函数 -
@MatG 哦,对。我之前没有注意到这一点。解决方案是什么?我是否应该编写一个从
std::invalid_argument派生的异常类,它有一个通过右值引用获取味精的ctor?这还能用吗? -
为什么需要移动字符串?请注意,由于小字符串优化,小字符串总是被复制
-
cppreference reads: 因为复制
std::invalid_argument不允许抛出异常,所以该消息通常在内部存储为单独分配的引用计数字符串。这也是为什么没有构造函数采用std::string&&:无论如何它都必须复制内容。
标签: c++ exception move-semantics stdstring