1

I am struggling to grasp rvalues in C++. Specifically, I don't understand where they are allocated and why they need to be immutable. Let's assume I have the following code:

  std::string str = std::string(); 
  const std::string& sref = std::string();

The first line creates an object in the stack. The object str is a mutable object and I can do whatever I want with it. The expression on the right of the assignment is rvalue while str is lvalue as far I've understood.

The second line creates an object in the current function stack ( I presume ) and it returns a const reference to it. The object so created is immutable. Again, the right side of the assignment is a rvalue, but this time I got a reference to rvalue. All reference, to a rvalue MUST be const because according to C++ standard you cannot change the value of rvalue. First question where is sref allocated in the current function stack? Why must it be immutable? I really don't understand why if the object is in the stack, I cannot just modify it.

If an object is immutable, it would make sense to have just one instance of it and then make all references in the application to point to it.

const std::string& ref_1 = std::string();
const std::string& ref_2 = std::string();

are these two refs referring to the same object in C++?

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
Giuseppe Pes
  • 7,772
  • 3
  • 52
  • 90
  • C is not C++ is not "C with classes". – too honest for this site Mar 28 '16 at 18:06
  • 1
    @Olaf: Where did the OP suggest that it is? – Lightness Races in Orbit Mar 28 '16 at 18:07
  • @Olaf I don't understand your comment? How is that relate to my question? Where do I mention C? – Giuseppe Pes Mar 28 '16 at 18:07
  • @GiuseppePes: You _did_ tag the question [tag:c] at first. – Lightness Races in Orbit Mar 28 '16 at 18:08
  • @BarryTheHatchet Yes, it was just one of the `automatically` suggested tag which now has been removed. I would prefer to talk about C++ rather than post about tag. I made an error, anyone can just edit the question rather than put useless comment like the first one. – Giuseppe Pes Mar 28 '16 at 18:09
  • 2
    @GiuseppePes: It would be best if you used your brain to determine which tags are appropriate to your question, rather than just accepting every automatic suggestion! – Lightness Races in Orbit Mar 28 '16 at 18:10
  • ` std::string str = std::string(); ` is initialization syntax, so the `rvalue` you are talking about does not exist, and copy/move constructor is never called after default constructor. – user3528438 Mar 28 '16 at 18:13
  • 1
    @user3528438: No. The `std::string()` is an rvalue, and the copy/move constructor is perfectly entitled to be invoked here. Indeed, it is required to be invokable!! Even if copy elision ends up skipping it. – Lightness Races in Orbit Mar 28 '16 at 18:15
  • @GiuseppePes: If you are interested in low level details of memory, there is an excellent book I personally like. "Memory as a Programming Concept in C and C++" by Frantisek Franek. Chap 1-3 would be good enough to answer your question here, but you are welcome to read the whole book. – animageofmine Mar 28 '16 at 18:20
  • @GiuseppePes: You implied this by adding the C tag. – too honest for this site Mar 28 '16 at 18:22
  • @animageofmine: It is better _not_ to. Learn C++'s semantics before you learn the low-level details of one particular implementation. Then you will have enough background to be able to spot the mistakes in those books, which are plenty: they are often entirely ignorant of the modern realities of optimisation and so forth. – Lightness Races in Orbit Mar 28 '16 at 18:22
  • @animageofmine thank you for the reference! I will check it out. :) – Giuseppe Pes Mar 28 '16 at 18:22
  • @BarryTheHatchet: OP suggested that by adding the C tag. – too honest for this site Mar 28 '16 at 18:24
  • @BarryTheHatchet Interesting perspective. I am a bottoms up guy :-). If I don't understand the low level details, my mind won't let me grasp the rest. BTW, I am not sure as to where OP stands in level of expertise as far as C/C++ is concerned. I figured it was too hard to answer this question in 1 or 2 statements. Hence the reference. – animageofmine Mar 28 '16 at 18:26
  • @animageofmine: That was fine forty years ago but the implementation details are now _so_ dependent on external factors that they are extremely hard to teach accurately without an appreciation for the abstractions at work. e.g. all this "stack" and "heap" nonsense that bears to little relation to reality. Learning low-level concepts is fine as long as you learn them correctly, which most do not. – Lightness Races in Orbit Mar 28 '16 at 18:32
  • @BarryTheHatchet agreed on the part implementation details depends on a lot of variables these days. But the good part about c++ is, some basic concepts remain the same unlike some scripting languages, where there is no easy way to find out the internal implementation. – animageofmine Mar 28 '16 at 18:51

1 Answers1

2

It doesn't matter where they're allocated. Somewhere in memory on your computer, or perhaps not at all if they're optimised out. Don't worry about it.

They're not immutable — you could modify them if you like (try std::string().append('!')); it's just that you're only allowed to bind a temporary to a reference if it's a reference-to-const. And if you don't bind it to a reference, you can't actually name it later to do anything with it.

This limitation was intended to prevent programmer mistakes, because modifying a temporary is usually pointless, though Visual Studio relaxes that restriction. However, you can still make use of this lifetime-extension without const by using an rvalue reference:

std::string&& ref = std::string();
ref.append('!');
std::cout << ref << '\n';

Why would you do it? Who knows.

As for your final question (one question per question please next time), no, those two references refer to two, unrelated, temporary std::string objects.

Community
  • 1
  • 1
Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055