Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

lvalue initialization fails

Some sample code from the "The C++ Programming Language 4th Edition" makes me confusing. Here is my test cases.

Env gcc version 4.6.3 (Debian 4.6.3-14+rpi1) with -std=c++0x

  • Code1 string var {"Cambridge"}; string& r1 {var}; Compiling fails
  • Code2 string var {"Cambridge"}; string& r1 = var; Compiling Succeed
  • Code3 string var {"Cambridge"}; string&& r1 {var}; Compiling Succeed
  • Code1 Compiling Fails with g++ -g -DLINUX -std=c++0x -c src/dummy.cpp -o src/dummy.o src/dummy.cpp: In function ‘int main(int, char**)’: src/dummy.cpp:26:17: error: invalid initialization of non-const reference of type ‘std::string& {aka std::basic_string<char>&}’ from an rvalue of type ‘<brace-enclosed initializer list>’ make: *** [src/dummy.o] Error 1
  • Code1 should be ok according the books. Section 7.7.2 since var is a lvalue, but why code1 does not work but code3 works in my situation?
like image 626
Zhang Biao Avatar asked Oct 12 '13 07:10

Zhang Biao


1 Answers

It fails because it tries to bind an rvalue to an nonconst lvalue reference.

8.5.4 List-initialization

[#3]

-- Otherwise, if T is a reference type, a prvalue temporary of the type referenced by T is list-initialized, and the reference is bound to that temporary. [ Note: As usual, the binding will fail and the program is ill-formed if the reference type is an lvalue reference to a non-const type. — end note]

Check this example to verify that r1 is bound to a distinct object

#include <string>
#include <iostream>

int
main () {
  std::string var {"Cambridge"};
  const std::string& r1 {var}; 
  const std::string& r2 (var);

  var.clear ();

  std::cout << "var = " << var << std::endl;
  std::cout << "r1 = " << r1 << std::endl;
  std::cout << "r2 = " << r2 << std::endl;
}

and contrast that to r2.

PS. Now the question arises, why the following does not fail according to the above considerations:

int x;
int &y { x };

the standard says (in the same place as above, but the next clause):

-- Otherwise, if the initializer list has a single element, the object or reference is initialized from that element;

This clause explicitly mentions reference, in other words, initializing a reference is not described in a single clause, but there are a few possibilities (maybe tried in order of the clauses?), which explains why int & behaves this way.

like image 91
chill Avatar answered Sep 17 '22 05:09

chill