通过 value/reference/rvalue 使用 std::move(str) arg
Pass by value/reference/rvalue with a std::move(str) arg
我有以下代码:
//void func(const std::string &&i){
//void func(const std::string &i){
void func(const std::string i){
std::string val{i};
}
int main()
{
std::string d = "asdf";
func(std::move(d));
std::cout << d << std::endl;
}
当 i
是按值传递时,d
变为空,但如果我们按引用或右值引用传递,d
将保留其形式。有人可以解释发生了什么吗?
我知道 std::move
实际上并没有移动任何东西,而是通过将它转换为 xvalue 来使它接收的变量可移动。
顺便说一句,如果将 d
强制转换为 x 值,为什么当前状态下的代码会编译? func
当前设置为通过值参数传递,而不是通过右值引用传递。
When i is pass-by-value, d becomes empty,
准确地说,d
将处于 C++ 标准中未指定的某个有效状态。空是一种可能。
std::move
本身不会导致直接调用移动构造函数。将右值引用绑定到对象也不会导致直接调用移动构造函数。
只有用非 const 右值初始化对象才会导致参数被移出。在示例中,std::string i
被初始化为一个非 const 右值,移动构造函数将被调用。
As an aside why does the code in the current state compile if d is cast to an x-value?
因为该类型有一个(未删除的)移动构造函数。因此,参数可以从右值初始化。
I had thought if we had std::string i, a copy of the rvalue reference is made.
std::string i
不是参考。它是一个 std::string
类型的变量,因此有一个 std::string
类型的对象与该变量相关联。该对象使用作为参数传递给函数的表达式进行初始化。
Also, if I observe that the output of d is still the same as prior to applying std::move, what does this mean in this case?
如果您使用右值调用函数的未注释版本,则参数将从中移出。如果该值与原来相同,则仅表示该值相同。您不能假设该值将相同,也不能假设它不会相同。
Does it mean that d is still occupying the space it originally occupied?
假设"space"你指的是变量所在的存储空间,那么它当然仍然占用相同的存储空间。对象的地址在对象的生命周期内永远不会改变。
void func(const std::string &&i)
此签名不会移动任何内容,因为引用是对 const
对象的引用。删除 const
,它将起作用。但前提是您再次在函数内 std::move
参数 i
。这是因为任何有名称的东西都是 lvalue
,无论参数声明为 &
还是 &&
。参见 。
void func(const std::string &i)
正如您可能已经知道的那样,这将被复制。但是,它的行为与 ptevious 类似,因为如果您在函数内放下 const
并执行 std::move( i )
,它实际上会移动。这是因为,正如您所指出的,move
是一个强制转换,编译器会听取您的意见并完全按照您在强制转换时所说的去做,而不管您的意图如何。
void func(const std::string i)
这会在您的示例中移动,因为此处 i
是一个全新的字符串。外部字符串 d
被移入 i
。但是,如果要将 i
移动到 val
,您仍然必须删除 const
并使用 std::move( i )
。
我有以下代码:
//void func(const std::string &&i){
//void func(const std::string &i){
void func(const std::string i){
std::string val{i};
}
int main()
{
std::string d = "asdf";
func(std::move(d));
std::cout << d << std::endl;
}
当 i
是按值传递时,d
变为空,但如果我们按引用或右值引用传递,d
将保留其形式。有人可以解释发生了什么吗?
我知道 std::move
实际上并没有移动任何东西,而是通过将它转换为 xvalue 来使它接收的变量可移动。
顺便说一句,如果将 d
强制转换为 x 值,为什么当前状态下的代码会编译? func
当前设置为通过值参数传递,而不是通过右值引用传递。
When i is pass-by-value, d becomes empty,
准确地说,d
将处于 C++ 标准中未指定的某个有效状态。空是一种可能。
std::move
本身不会导致直接调用移动构造函数。将右值引用绑定到对象也不会导致直接调用移动构造函数。
只有用非 const 右值初始化对象才会导致参数被移出。在示例中,std::string i
被初始化为一个非 const 右值,移动构造函数将被调用。
As an aside why does the code in the current state compile if d is cast to an x-value?
因为该类型有一个(未删除的)移动构造函数。因此,参数可以从右值初始化。
I had thought if we had std::string i, a copy of the rvalue reference is made.
std::string i
不是参考。它是一个 std::string
类型的变量,因此有一个 std::string
类型的对象与该变量相关联。该对象使用作为参数传递给函数的表达式进行初始化。
Also, if I observe that the output of d is still the same as prior to applying std::move, what does this mean in this case?
如果您使用右值调用函数的未注释版本,则参数将从中移出。如果该值与原来相同,则仅表示该值相同。您不能假设该值将相同,也不能假设它不会相同。
Does it mean that d is still occupying the space it originally occupied?
假设"space"你指的是变量所在的存储空间,那么它当然仍然占用相同的存储空间。对象的地址在对象的生命周期内永远不会改变。
void func(const std::string &&i)
此签名不会移动任何内容,因为引用是对 const
对象的引用。删除 const
,它将起作用。但前提是您再次在函数内 std::move
参数 i
。这是因为任何有名称的东西都是 lvalue
,无论参数声明为 &
还是 &&
。参见
void func(const std::string &i)
正如您可能已经知道的那样,这将被复制。但是,它的行为与 ptevious 类似,因为如果您在函数内放下 const
并执行 std::move( i )
,它实际上会移动。这是因为,正如您所指出的,move
是一个强制转换,编译器会听取您的意见并完全按照您在强制转换时所说的去做,而不管您的意图如何。
void func(const std::string i)
这会在您的示例中移动,因为此处 i
是一个全新的字符串。外部字符串 d
被移入 i
。但是,如果要将 i
移动到 val
,您仍然必须删除 const
并使用 std::move( i )
。