Is it valid to bind non-const lvalue-references to rvalues in C++ 11?(modified)

此生再无相见时 提交于 2019-11-26 09:57:24

问题


I know in c++03, an an non-const reference cannot be bound to rvalues.

T& t = getT(); is invalid, and in c++11, we can do this: T&& t = getT(); but what about the above code, should that work in c++11?

I tested the codes below with vs11:

 Foo getFoo() {
  return Foo();
}

void fz(Foo& f) {
}

int getInt() {
  return int();
}

void iz(int& i) {
}

int main() {
  {
    Foo& z = getFoo(); //ok
    fz(getFoo()); //ok

    int& z2 = getInt(); //error: initial value of reference to non-const must be an lvalue
    iz(getInt()); //same as above
  }
}

Foo is a custom class, I don\'t understand why the first two line compiles.The temporary referenced by z is destructed at the end of the inner scope of main. Does the standard say anything about this?

class Foo {
public:
  Foo() {
    std::cout << \"constructed\\n\";
  }
  ~Foo() {
    std::cout << \"destructed\\n\";
  }
};

I just saw a similar question: One VS2010 bug ? Allowing binding non-const reference to rvalue WITHOUT EVEN a warning?


回答1:


should that work in c++11?

No, it should not.

Foo is a custom class, I don't understand why the first two line compiles

It compiles only with MSVC. MSVC has an (arguably useful) compiler extension that allows binding lvalues of user-defined types to rvalues, but the Standard itself forbids this. See, for instance, this live example where GCC 4.7.2 refuses to compile your code.

Does the standard say anything about this?

Indeed it does. Per paragraph 8.5.3/5 of the C++11 Standard:

A reference to type “cv1 T1” is initialized by an expression of type “cv2 T2” as follows:

— If the reference is an lvalue reference and the initializer expression

— is an lvalue (but is not a bit-field), and “cv1 T1” is reference-compatible with “cv2 T2,” or

— has a class type (i.e., T2 is a class type), where T1 is not reference-related to T2, and can be implicitly converted to an lvalue of type “cv3 T3,” where “cv1 T1” is reference-compatible with “cv3 T3” [...],

then the reference is bound to the initializer expression lvalue in the first case and to the lvalue result of the conversion in the second case (or, in either case, to the appropriate base class subobject of the object). [...]

[ ...]

Otherwise, the reference shall be an lvalue reference to a non-volatile const type (i.e., cv1 shall be const), or the reference shall be an rvalue reference. [ Example:

double& rd2 = 2.0; // error: not an lvalue and reference not const
int i = 2;
double& rd3 = i; // error: type mismatch and reference not const

—end example ]




回答2:


No you can't bind a temporary to a non-const lvalue reference.

T f();

T& t1 = f(); // won't compile
const T& t2 = f(); // OK
T&& t3 = f(); // OK

This is a safety feature. Mutating a temporary by an lvalue that is about to die anyway is most likely a logic error, so it isn't allowed by the language.

Note that due to the RVO than in practice:

T&& t3 = f();

and

T t3 = f();

are equivilent.



来源:https://stackoverflow.com/questions/16493524/is-it-valid-to-bind-non-const-lvalue-references-to-rvalues-in-c-11modified

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!