4

I have the following code:

#include <iostream> using namespace std; int main(int argc, char *argv[]) { string &s1 = argv[0]; // error const string &s2 = argv[0]; // ok argv[0] = "abc"; cout << argv[0] << endl; // prints "abc" cout << s2 << endl; // prints program name } 

I receive the following error for s1:

invalid initialization of reference of type 'std::string& {aka std::basic_string<char>&}' from expression of type 'char*' 

Then why does the compiler accept s2?

Interestingly, when I assign a new value to argv[0] then s2 does not change. Does the compiler ignore that it's a reference and copies the value anyway? Why does it happen?

I write this in Code::Blocks 16.01 (mingw). The same happens with/without -std=c++11.

2
  • 1
    Would you say that argv[0] is an std::string? Commented Sep 18, 2016 at 12:51
  • "Then why does the compiler accept s2?" because of implicit conversion. stackoverflow.com/questions/4553896/… Commented Sep 18, 2016 at 12:56

4 Answers 4

7

Then why does the compiler accept s2?

Because a constant reference can bind to a temporary, and std::string has a constructor that can take a char * for a parameter.

That assignment constructs a so-called "temporary" object, and binds a constant reference to it.

Interestingly, when I assign a new value to argv[0] then s2 does not change.

Why should it change? s2 is a separate object. A std::string object does not maintain a pointer to a char * that created it. There are many ways to create a std::string. The actual string is owned by the object. If the std::string is constructed from a literal character string, it gets copied into the std::string. So, if the literal character string comes from a buffer, and the buffer is subsequently modified, it has no effect on the std::string.

Sign up to request clarification or add additional context in comments.

3 Comments

The constructor of a std::string takes a const char * for a parameter. Am I wrong?
No you're not, @skypjack. That's why I wrote "can take", instead of "takes".
And with special emphasis on a const reference can bind to a temporary
5

This line:

const string &s2 = argv[0]; 

Creates a new string instance, copying the contents of argv[0], and binds the reference to it. Later, this copy is outputted, which is now unrelated to the actual value of argv[0].

The temporary string objects lifetime, created in the quoted line, is expanded to the scope of the block, because a const reference was formed to it. See more at: Does a const reference prolong the life of a temporary?

Comments

1

In both cases, the code asks the compiler to construct a temporary std::string object whose content is a copy of argv[0]. While it's fun and maybe useful to look at the details of which one works and why, in terms of actually writing code, messing around with temporaries isn't necessary and leads to confusion. Just create an object:

std::string s1 = argv[0]; 

Comments

1

The line

const string &s2 = argv[0]; 

is equal to:

const string &s2 = std::string(argv[0]); 

So s2 contains a const reference to a temporary string, which copied the content from argv[0].

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.