Home > Net >  Why is it ok to assign a std::string& to a std::string variable in c ?
Why is it ok to assign a std::string& to a std::string variable in c ?

Time:05-19

class MyClass:
public:
   MyClass(const std::string& my_str);
private:
  std::string _myStr

In the implementation:

MyClass::MyClass(const std::string& my_str):
   _mystr(my_str)

How can you assign a reference (my_str is const std::string&) to a non-reference variable (_mystr, which is std::string) ?

In my mental model, a variable is a block of space in memory can be filled with stuff that is the same type as the variable's declared type. So a std::string variable is a block of space that can hold a string (eg: "abcd"), while a const std::string& is a block of space in memory that can hold a "reference" (kind of vague what it is, unlike a pointer which is an address to another block in memory). When you assign one variable to another, you are copying the content stored in one memory block into another. So how can you copy a std::string& into a std::string - their types are different.

What am I mis-understanding here?

CodePudding user response:

my_str is a name for another string. The "mental model" you are using is that of a pointer to another string, but a reference is not a pointer.

What's your mental model for this code?

std::string s1, s2;
s1 = s2;  

Use that same model for the code in the question; my_str names a std::string somewhere in memory, just as s2 does.


Also note that assignment of class types means to call an assignment operator function, which is not the same as copying content of a memory block. One of the ideas of object-oriented programming is that assigning from one object to another brings the objects to have the same logical meaning, not the same memory content.

For example, string is often structured as a small memory block with an internal pointer to a large dynamically allocated block. Two different string objects will each have allocated their own blocks, even if assigned to have the same content stored in that block for now. You certainly wouldn't want to implement s1 = s2; by copying the memory block of s2 to s1. Instead you want to copy between the managed allocations of each string (and resize s1's allocation if needed).


One more thing: the code in your question is doing construction and not assignment . Those are different things, as assignment must update a valid state that already exists.

But these same considerations apply to both cases.

CodePudding user response:

In your case you do not make an assignment actually. This line:

_mystr(my_str)

Is involing the copy contructor of your _mystr member.
The copy contstructor received a const std::string& (my_str in your case), and constructs a clone of the object it refernces into your member _mystr.

But to answer your question in a more general way: It is possible to assign a variable of type refernce into a non refernce type.
What will happen is the the assignment operator of the target will be invoked. The assignment operator (of std::string in this case) accepts (like the copy constructor) a const std::string&, and assigns a clone of the object it refernces into your member _mystr. Therefor this will work as well:

void f(std::string const & str)
{
   std::string local_str = str;
   // ...
}

All the above is correct in general for all classes.
Non-class types behaves in a similar manner, e.g.:

int i1;
int & ri1 = i1;
int i2 = ri1;  // Will assign a copy of the value refernces by ri1, i.e. the value of i1 into i2

See more here about Initialisation and assignment.
And Why are initialization lists preferred over assignments?.

CodePudding user response:

_mystr(my_str) is invoking the copy constructor of std::basic_string to initialize _mystr with a string identical (in characters) to the string in my_str; see (7) in https://en.cppreference.com/w/cpp/string/basic_string/basic_string.

CodePudding user response:

The part that matters here is that the _myStr has a non-reference type. And in general, the type of the variable we initialize (e.g. the left-hand operand in =) dictates how the initialization will proceed.

_myStr uses whatever the my_str refers to as a value to copy into itself. The _myStr does not become a reference when it uses a reference to initialize itself, since its type does not specify it to do so.

It is irrelevant whether my_str is a reference or not, _myStr will always store a copy.


Note, you don't worry about the fact that my_str is const while the _myStr is not a const. Same goes for the reference type specifier - both the const and & are absent in the type of the _myStr. Thus, it does not "refer" (self-contained) and is not constant.

Among the others, it is this ability to specify the (static) types what beings this enormous amount of diversity of consequent behaviors of objects in C .

  •  Tags:  
  • c
  • Related