Daniel Mernyei
Daniel Mernyei

Reputation: 51

Convert char* to string&

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

Answers (4)

Kilian
Kilian

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

Pete Becker
Pete Becker

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

erenon
erenon

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

Sam Varshavchik
Sam Varshavchik

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

Related Questions