Reputation: 51
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
.
Upvotes: 4
Views: 548
Reputation: 543
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].
Upvotes: 1
Reputation: 76458
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];
Upvotes: 1
Reputation: 19128
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?
Upvotes: 5
Reputation: 118425
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
.
Upvotes: 7