-1
void PrintName(string&& name) {
    cout << "[rvalue] " << name << endl;
}

void PrintName(string& name) {
    cout << "[lvalue] " << name << endl;
}


int main() {
    string name{"Charles"};
    PrintName(name); // [lvalue] Charles
    PrintName("Charles"); // [rvalue] Charles
}

I overloaded the PrintName to accept both the rvalue and lvalue. When I call it with a lvalue name, it works fine and outputs [lvalue] Charles; When I call it with "Charles" directly, it chooses to run the rvalue version and outputs [rvalue] Charles. However, I heard that the string literal is lvalue, so why doesn't "Charles" call the lvalue version of the PrintName? And, how can we write some code to prove that the string literal is lvalue?

With the help of the comments and answers, I finally figured out to write a piece of code to prove that a string literal is a lvalue

typedef const char stringliteral[8];

void PrintName(stringliteral&& name) {
    cout << "[rvalue] " << name << endl;
}
void PrintName(stringliteral& name) {
    cout << "[lvalue] " << name << endl;
}

Call PrintName by "Charles" will run the rvalue version.

  • 6
    Because "Charles" will first be implicitly converted to an rvalue of `std::string` and then passed to the function. – Lingxi May 09 '22 at 03:01
  • 2
    `"[rvalue] "` is a `const char [N]`, not `std::string` – phuclv May 09 '22 at 03:04
  • @Lingxi Could you write some code example that can prove the lvalueness of the string literal? – charles yin May 09 '22 at 03:14
  • @charlesyin Whether string literal is of lvalue or rvalue is irrelevant in your case. It will be converted to `std::string` anyway. So what's the matter? – Lingxi May 09 '22 at 03:18
  • @Lingxi I finally figured out a way to prove that a string literal is a lvalue, as shown in the updated question. – charles yin May 09 '22 at 03:27
  • @user207421 Yes, it definitely is! – charles yin May 09 '22 at 03:29
  • @charlesyin Citation please. Is a numeric literal an lvalue too? It doesn't make sense. – user207421 May 09 '22 at 03:36
  • @user207421 per [expr.prim.literal](http://eel.is/c++draft/expr.prim.literal): "*A string-literal is an lvalue designating a corresponding string literal object ([lex.string](http://eel.is/c++draft/lex.string))*" – Remy Lebeau May 09 '22 at 03:38

2 Answers2

1

"Charles" is not a string, it's const char [8]. When call PrintName, It implicitly create a string, so it's a right value.

macomphy
  • 413
  • 1
  • 9
-1

The string literal is not an lvalue. The reason is that string literals are stored in the .rodata (read-only data) section (see this site for more info) and thus cannot be modified, hence it is an rvalue.

Update: I stand corrected on the matter of string literals not being lvalues: see here.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
fireshadow52
  • 6,298
  • 2
  • 30
  • 46
  • Actually, a string literal IS an lvalue, per [expr.prim.literal]. But you are correct that you can't safely write to the memory occured by a string literal, doing so is undefined behavior. – Remy Lebeau May 09 '22 at 03:35