2

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?

Ryan
  • 7,621
  • 5
  • 18
  • 31
  • 2
    I can't get your question. You can make a copy, the copy might be non-const or const; anyway, it has nothing to do with the original object (after being copied). – songyuanyao Jan 05 '17 at 07:45
  • not sure if that is your misunderstanding, but in `const int x = 5` it is `x` that is `const` not the value. E.g. `int y = x` is perfectly fine, as well as `y = 3` afterwards. The reference doesnt change that – 463035818_is_not_an_ai Jan 05 '17 at 07:48
  • Remember, a reference is basically the same as a pointer (that can't be null). So when you're asking yourself why something with a reference works, try saying "pointer" instead and see if it makes more sense that way. – xaxxon Jan 05 '17 at 07:57
  • "we are assigning a reference to a const string to a string" - no, you're *initializing* a new `std:string` from an existing reference to a `const std::string`. Later on you say, "..we can make a copy of a const object" - operative words there: *"make a copy"*. That's exactly what is happening in the member initialization list, leaving you a modifiable `std::string` as your member. See [#7 from here](http://en.cppreference.com/w/cpp/string/basic_string/basic_string). – WhozCraig Jan 05 '17 at 08:18

3 Answers3

3

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 );
Ralph Tandetzky
  • 22,780
  • 11
  • 73
  • 120
1

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.
Community
  • 1
  • 1
frogatto
  • 28,539
  • 11
  • 83
  • 129
1

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 &.

Potatoswatter
  • 134,909
  • 25
  • 265
  • 421