Ryan
Ryan

Reputation: 8241

Understanding assignment of const reference to non-cost data member

I am reviewing C++ references any am trying to reason why the following piece of code complies:

#include <string>

class Foo {

public:

    Foo(const std::string& label)
        : d_label(label) {}

private:

    std::string d_label;

};

int main(int argc, const char** argv) {
    Foo("test");
    return 0;
}

Here, we are assigning a reference to a const string to a string. In doing so, is a copy of label made that is non-const? If so, why is it that we can make a copy of a const object that is itself non-const? Otherwise, what exactly is going on here, in terms of copy constructor/assignment calls?

Upvotes: 2

Views: 291

Answers (3)

Ralph Tandetzky
Ralph Tandetzky

Reputation: 23640

In C++ the keyword const actually means read-only. To make a copy of an object, you don't need write access. Therefore, you can copy a const std::string into an std::string.

Also note, that copying in C++ means making a deep copy by default. This is called value semantics. Hence, manipulating the copied string will not do anything to the original string.

Now to your last question: What is going on in the following line?

Foo("test");

The type of "test" is const char[5]. The compiler searches for a matching constructor of Foo. Since "test" is implicitly convertible to std::string via the

basic_string<CharT,Alloc>::basic_string( const CharT * s, const Alloc & a = Alloc() );

constructor, this conversion will be performed, i. e. a temporary std::string is constructed from "test". A const reference to this temporary is then passed to the constructor

Foo::Foo( const std::string & label );

This constructor in turn calls std::strings copy constructor in order to construct the d_label member of Foo:

basic_string<CharT,Alloc>::basic_string( const basic_string & other );

Upvotes: 3

frogatto
frogatto

Reputation: 29285

Here no assignments take place. d_label(label) initializes the variable d_label with label which subsequently ends up calling copy constructor of string type.

Let's have a closer look:

  • Foo("test"); initializes const std::string& label with "test" which its type is const char[5]

  • Here a string reference (label) is getting initialized with a value having type const char[5]. This initialization is valid since "test" through decaying to const char * can be passed to one of string constructors which gets a const char *.

  • Now label is a reference to a real string object storing "test".
  • Then, d_label(label) initializes Foo::d_label with the object referred to by label.
  • At this point copy constructor of string type is called and constructs the Foo::d_label.

Upvotes: 1

Potatoswatter
Potatoswatter

Reputation: 137860

C++ offers both reference semantics and value semantics: Objects have values, and then you can take references to objects.

std::string d_label

d_label is an object holding a string value. It is considered to own the bytes holding the string as a memory resource. This notion of ownership rationalizes using d_label as an interface to modify the string.

const std::string& label

label is a read-only reference to a string. This is not quite the same as "a reference to a const string." It refers to an object that may be (and probably is) not const.

: d_label(label)

This initializes d_label with the content of label using a copy constructor. You may then do what you like with the copy. You know that the process of copying won't modify the underlying object of label because label was declared const &.

Upvotes: 1

Related Questions