C++11 如果我有T&&;温度=标准::移动(其他);然后将其用于按值接受T的函数

C++11 如果我有T&&;温度=标准::移动(其他);然后将其用于按值接受T的函数,c++11,move,move-semantics,C++11,Move,Move Semantics,假设我有一个下面的函数: void foo(std::string strParam) // pass-by-value { // function-body } 所以foo(string)的strParam将通过copy(如果arg是左值)或move(如果arg是右值)创建 众所周知, foo("blah"); // rvalue; so string move constructor invoked for strParam. 对, string bar = "blah"; fo

假设我有一个下面的函数:

void foo(std::string strParam) // pass-by-value
{
    // function-body
}
所以foo(string)的strParam将通过copy(如果arg是左值)或move(如果arg是右值)创建

众所周知,

foo("blah"); // rvalue; so string move constructor invoked for strParam.
对,

string bar = "blah";
foo(bar); // lvalue; so string copy constructor invoked for strParam.
再说一遍

string bar = "blah";
foo(move(bar)); // xvalue; so move constructor.
和用于命名的右值引用变量

string &&temp = // can be whatever
foo(temp); // *named* rvalue reference IS a lvalue; so copy constructor.
我猜这意味着

string &&movedBar = move(bar);
foo(movedBar); // it actually invokes copy constructor.
因此

foo(move(bar)) 
不同于

string&& movedBar = move(bar);
foo(movedBar)
因为一个是未命名的右值引用(xvalue),另一个是命名的右值引用(左值)

没错,对吗?

一个更正:

foo("blah"); // rvalue; so string move constructor invoked for strParam.
这实际上调用了采用
const char*
std::string
构造函数,而不是
std::string
move构造函数。这是重载集中唯一的
std::string
构造函数-其他所有内容都将涉及多个用户定义的转换

在每一点上,你都是正确的。总结如下:

foo("blah"); // calls string constructor that takes a const char*
foo(bar); // calls string copy ctor
foo(move(bar)); // calls string move ctor

string&& movedBar = move(bar);
foo(movedBar); // calls copy ctor
Update:正如评论中指出的,
foo(“blah”)
实际上会调用两个构造函数,就好像它实际上是
foo(string(“blah”)
。首先,从
“blah”
构造一个临时字符串,并将该临时字符串移动到
strParam
中。然而,第二步可能会被省略,因为
string strParam(string(“blah”)
是多余的。这可以通过
delete
-ing自定义小部件的移动构造函数或使用
-fno-elide构造函数编译来验证


或者,正如我喜欢看的那样,我们都是对的。调用
常量char*
,并调用字符串move构造函数(~ish?)

string&&movedBar=move(bar)
&&
代表[universal reference][0][0]中,命名对象被视为左值。要传播对象的右值,必须将其强制转换为右值(即
std::move()
)。@erenon它不是一个通用引用(即使在链接的定义中),即使它是,也没关系-它会被推导出为左值引用或右值引用,在这两种情况下,下一行将其视为左值-如果其类型为auto&&(或在模板中涉及类型推断T),则它将是一个通用引用;即使我确实使用auto&&作为它的类型(如果我编写它auto&&movedBar=move(bar)),类型也会被推断为string&&作为右值引用,但它是一个命名的右值引用,所以它是一个lvalue@0x499602D2我发现谈论对象的价值类别令人困惑。值类别是表达式的属性。因此,id表达式
movedBar
是左值,函数调用表达式
move(bar)
是右值。调用
foo(“blah”)
似乎需要
const char*
构造函数和move构造函数。但是,移动构造函数可能会被省略。我试着用
std::string
重写代码,替换为一个自定义
小部件
类,该类具有
=delete
ed移动构造函数。