Reputation: 8241
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
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::string
s copy constructor in order to construct the d_label
member of Foo
:
basic_string<CharT,Alloc>::basic_string( const basic_string & other );
Upvotes: 3
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 *
.
label
is a reference to a real string object storing "test"
.d_label(label)
initializes Foo::d_label
with the object referred to by label
.string
type is called and constructs the Foo::d_label
.Upvotes: 1
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