C++ 理解警告:将r值绑定到l值引用

C++ 理解警告:将r值绑定到l值引用,c++,c++11,syntax,resharper,rvalue,C++,C++11,Syntax,Resharper,Rvalue,我想通过引用传递一个结构,这样它就不会被复制,但Resharper给出了以下警告: struct sometype { }; sometype foo() { sometype x; return x; } void bar() { sometype & a = foo();//Binding r-value to l-value reference is non-standard Microsoft C++ extension sometype &a

我想通过引用传递一个结构,这样它就不会被复制,但Resharper给出了以下警告:

struct sometype {
};

sometype foo() {
    sometype x;
    return x;
}

void bar() {
    sometype & a = foo();//Binding r-value to l-value reference is non-standard Microsoft C++ extension
    sometype && b = foo(); //ok
}
问题:

sometype&a=foo()有什么问题
foo()
的返回值不是左值,而
a
也是左值吗

Is
sometype&&b=foo()实际右值引用?它是否从
foo()
中“窃取”返回值,并将
b
中的内容发送到析构函数


有没有其他方法不显示此警告?

您正在引用一个临时对象。唯一合法的方法是:

常量对象&
(常量l值参考),或

对象&
(可变r值参考)

这是(故意的)语言限制

进一步讨论:

将临时变量分配给引用会延长临时变量的生存期,使其与引用的生存期相匹配。因此,令许多初学者惊讶的是,这是合法的:

{
  const string& s = foo();
  cout << s << endl;         // the temporary to which s refers is still alive
}
// but now it's destroyed
string&& s = foo();    // extends lifetime as before
s += "bar";
baz(std::move(s));     // move the temporary into the baz function.
以下是一个更现实的原因,说明它可能是一个逻辑错误:

string foo();         // function returning a string
void bar(string& s);  // this function is asserting that it intends to *modify*
                      // the string you sent it

// therefore:

bar(foo());           // makes no sense. bar is modifying a string that will be discarded.
                      // therefore assumed to be a logic error
您必须将上述内容替换为:

  string s = foo();
  s += "bar";
  // do something here with s
请注意,在命名变量(l值)中捕获临时变量没有任何开销

r值引用被设计为移动构造函数或移动赋值的主题。因此,它们是可变的是有道理的。它们的本质意味着物体是暂时的

因此,这是合法的:

{
  const string& s = foo();
  cout << s << endl;         // the temporary to which s refers is still alive
}
// but now it's destroyed
string&& s = foo();    // extends lifetime as before
s += "bar";
baz(std::move(s));     // move the temporary into the baz function.
它可能会帮助您记住,指定
&&
就是断言您知道变量是可变的临时变量

但允许这样做的真正原因是这样做会起作用:

string foo();   // function that returns a string
void bar(string&& s);  // function that takes ownership of s

bar(foo());  // get a string from foo and move it into bar

// or more verbosely:

string s = foo();
bar(move(s));
在c++11之前,bar必须以以下方式之一编写:

void bar(string s);   // copy a string

// resulting in:

const string& s = foo();
bar(s);  // extra redundant copy made here

void bar(const string& s); // const l-value reference - we *may* copy it
// resulting in:

const string& s = foo();
bar(s);  // maybe an extra redundant copy made here, it's up to bar().
sometype&a=foo();;有什么问题吗

foo()返回temporary,因此无法将其绑定到引用,因为在完整表达式(赋值行)结束后,它将不再存在。延长其使用寿命的唯一方法是将其更改为
constsometype&a=foo()或将其分配给右值引用

是sometype&&b=foo();实际上是右值引用

是(请阅读此处了解更多信息:)

它是否从foo()中“窃取”返回值并将b中的内容发送到析构函数

不,它延长了它的寿命

有没有其他方法可以避免此警告

您有三种选择:(1)分配给右值引用,(2)分配给常量左值引用,(3)按值返回,但在类中实现移动语义


您也可以指望编译器会对返回值执行RVO。

是否将
对象&&
视为右值引用?将常量添加到
常量对象&
的动机是什么?是的。在这种情况下,它是一个r值引用。最初的想法是,对临时变量进行可变引用是没有意义的,因为临时变量将被丢弃。对临时对象调用可变方法通常是一个逻辑错误,因此是不允许的。指定r值引用本质上表明您知道自己在做什么。我看到您在上一个代码片段中添加了更多示例,即
bar(foo())盗取右值引用的臭名昭著行为?