我想通过引用传递一个struct,因此它不会被复制,但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也是左值?
是某种类型&& b = foo();实际左右参考?它是否“窃取”foo()的返回值并将b中的内容发送给析构函数?
还有另一种方法没有这个警告吗?
解决方法
您正在引用临时对象.唯一合法的方法是:
const对象& (const l-value reference),或
对象&安培;&安培; (可变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(); // this is not possible s += "bar"; // therefore neither is this // the implication is that since you modified s,you probably want to // preserve it } // ... but now it's destroyed and you did nothing with it.
这是一个更现实的原因,为什么它可能是一个逻辑错误,给出:
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值引用被设计为移动构造函数或移动赋值的主题.因此,它们是可变的是有意义的.它们的本质意味着物体是瞬态的.
因此,这是合法的:
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().