std::string 的 move ctor 不能正常工作?
move ctor of std::string does not work properly?
为什么 msg
在调用 std::move(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
的构造函数而不是复制它。我认为应该修改 msg
,并在调用 std::move
后将其保留在未指定但有效的状态。但这种情况发生了:
before try-catch: Error!
Error!
after try-catch: Error!
为什么会这样? std::string
的 move ctor 没有被调用吗?或者这是某种积极的编译器优化,尽管使用了 -O0 选项?
在这里,std::invalid_argument
中唯一相关的constructor是:
invalid_argument(const std::string& what_arg);
Const-ref 参数可以绑定到任何东西,包括 xvalue,std::move(msg)
就是。 std::move()
本身只是一个转换,将数据从字符串中移出的真正工作可以在构造函数中完成。但是你不能修改 const-ref 获取的 xvalue。您唯一的选择是复制一份,不修改 msg
。
Cppreference 具有以下 note,这解释了缺少采用 std::string&&
的构造函数:
Because copying std::invalid_argument
is not permitted to throw exceptions, this message is typically stored internally as a separately-allocated reference-counted string. This is also why there is no constructor taking std::string&&
: it would have to copy the content anyway.
为什么 msg
在调用 std::move(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
的构造函数而不是复制它。我认为应该修改 msg
,并在调用 std::move
后将其保留在未指定但有效的状态。但这种情况发生了:
before try-catch: Error!
Error!
after try-catch: Error!
为什么会这样? std::string
的 move ctor 没有被调用吗?或者这是某种积极的编译器优化,尽管使用了 -O0 选项?
在这里,std::invalid_argument
中唯一相关的constructor是:
invalid_argument(const std::string& what_arg);
Const-ref 参数可以绑定到任何东西,包括 xvalue,std::move(msg)
就是。 std::move()
本身只是一个转换,将数据从字符串中移出的真正工作可以在构造函数中完成。但是你不能修改 const-ref 获取的 xvalue。您唯一的选择是复制一份,不修改 msg
。
Cppreference 具有以下 note,这解释了缺少采用 std::string&&
的构造函数:
Because copying
std::invalid_argument
is not permitted to throw exceptions, this message is typically stored internally as a separately-allocated reference-counted string. This is also why there is no constructor takingstd::string&&
: it would have to copy the content anyway.