0

To use returned object from functions, could anyone tell me why case 1, 3, 4 are OK but not 2 in this code?

#include <iostream>
using namespace std;

class X {
    int i;
public:
    X(int ii = 0) : i(ii) {};
    void modify() { i++; };
};

X f1() { return X(1); }

// Pass by non-const reference
void f20(X& x) { x.modify(); }
// Pass by const reference
void f21(const X& x) { }
// Pass by value
void f22(X x) { x.modify(); }

int main() {
    f1() = X(2); // 1. OK
    //! f20(f1());   // 2. Bad
    f21(f1());   // 3. OK
    f22(f1());   // 4. OK
}

Thank you!

user1443721
  • 1,110
  • 2
  • 14
  • 33

2 Answers2

1

Because temporaries can't be bound to lvalue reference to non-const.

The main rationale I've seen bandied about is that otherwise (as with the Visual C++ language extension) a function like

void increment( int& value ) { ++value; }

might be called like

auto main() -> int
{
    increment( 2+2 );
}

but I'm not sure that's entirely convincing.

The rules do help with much coding, but as the Visual C++ language extension (allowing the binding for class types) exemplify, it's not crucial and not much an issue in ordinary code.


In passing, note that a temporary object is not const, unless it has been declared as such. In particular you can call non-const member functions on it, like in your case f1().modify(). You just can’t bind it to an lvalue reference to non-const.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • This is from thinking in C++ v1, ch8. Sometimes, during the evaluation of an expression, the compiler must create temporary objects. These are objects like any other: they require storage and they must be constructed and destroyed. The difference is that you never see them – the compiler is responsible for deciding that they’re needed and the details of their existence. But there is one thing about temporaries: they’re automatically const. – user1443721 Aug 03 '14 at 00:13
  • @user1443721: You shouldn't dismiss "Thinking in C++" on that account alone. It's one of the very few free C++ books. Unfortunately, the good Bruce Eckel has not followed up by considering errata, so the book is as full of mistakes as it was when the raw manuscript was finished. There is a partial 3rd party errata list at (http://www.computersciencelab.com/Eckel.htm). For some higher quality books, which cost some money, see the [Definitive C++ book list](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) here on SO. – Cheers and hth. - Alf Aug 03 '14 at 00:20
  • Sorry for the reference, **the SO book list HAS BEEN VANDALIZED** by SO moderator [George Stocker](http://stackoverflow.com/users/16587/george-stocker). On the 20th of March he added various items in a summary, and included a completely misleading entry for "Thinking in C++". On the same date he deleted all the existing entries, you probably need some high SO reputation to see them. :( – Cheers and hth. - Alf Aug 03 '14 at 00:29
  • Thanks to point it out. In fact, I doubt the statement (const temporary object) but I don't have source to reject it. The case 1 in my code may be the evidence that it is not const. – user1443721 Aug 03 '14 at 00:52
  • A more pressing problem is that the "extension" makes it easier to accidentally create dangling references. – M.M Aug 03 '14 at 02:15
  • @Alf the "vandalism" appears to be moving the answer out of the question and into an answer ... perhaps start a meta thread if you want it reverted – M.M Aug 03 '14 at 02:23
  • @MattMcNabb: there is no "the" answer to a book list. that's the vandalism. before he destroyed it, we had a dynamic book list with ordinary voting and useful comments (e.g., for the case at hand, links to the downloads of "Thinking in C++", I reinstated them in the summary after discovering the vandalism, but it's probably like that for all the others), plus a summary IIRC. It's completely useless now, not better than any other such list. It has upvotes due to earlier popularity. – Cheers and hth. - Alf Aug 03 '14 at 05:13
  • also, the "out of the question and into an answer" doesn't make sense at all. maybe you have looked at some other thing, not the book list. and meta is, as you know, for the politicians here. the folks who think there is a "the" answer to a book list, just treating any paper as toilet paper. no sense of quality, no thinking or intelligence. just associative & rule-bound. argh. – Cheers and hth. - Alf Aug 03 '14 at 05:16
  • A meta discussion will get better results than a discussion in comments to an unrelated question – M.M Aug 03 '14 at 05:23
  • @MattMcNabb: re "will get better results", do you *really* think that user1443721 is closely following meta? or are you saying that instead of responding to you here (the other person I have responded to), i should respond in some meta thread you have started? well i don't see any point in that. sorry. this suggestion makes as little sense as your notion of a "the" answer to the booklist. well there is a "the" answer now, and it's worthless. – Cheers and hth. - Alf Aug 03 '14 at 05:27
  • @Alf you seem to be objecting to the changes made to the book list. If you would like to see the book list done differently then post on meta. It might result in the book list being fixed , which would be beneficial to the users – M.M Aug 03 '14 at 05:56
  • @MattMcNabb: if you think it only *seems* as if I object then you haven't been paying attention. and no i'm not going to do any meta discussion. either the lounge folks already did that, in which case it's hopeless, we're victims of elected politicians, or else they didn't, in which case we're victims of something else, perhaps letargy or apathy after umpteen useless such bouts (e.g. earlier the mods deleting all the highest voted questions on SO, because they didn't fit with their notion of "the" answer questions, i.e. googleability for monetization or whatever: politics). – Cheers and hth. - Alf Aug 03 '14 at 06:01
0

The f1() method returns the temporary object of type X.

The = operator can be applied to the object of type X, even though the object itself is not going to be available afterwards.

f21() expects const reference (i.e. something that isn't supposed to change within that function) so there is no check whether the reference is valid.

f22() expects the value itself, which is modified inside the function and then the modifications are lost.

f20() expects a reference, i.e. the changes which are made inside this function are supposed to apply to the object that exists outside of that function. But it gets a reference to a temporary object, therefore the problem.

If you want to return the reference to the non-temporary object, your function would have to look like:

X& f1() { return *(new X(1)); }

and you'll have to take care of deleting this object afterwards.

Ashalynd
  • 12,363
  • 2
  • 34
  • 37
  • I was told that temporary object is constant. If it is true, why does case 1 work? – user1443721 Aug 02 '14 at 23:52
  • Why shouldn't it work? You get the object and you apply a method to it. Nothing wrong with that. – Ashalynd Aug 02 '14 at 23:54
  • 1
    @user1443721: Temporary object are not constant, but they can't be bound to lvalue reference to non-const... – Jarod42 Aug 02 '14 at 23:59
  • If f1() returns a constant object, we cannot change its value by assign and/or copy constructor, right? – user1443721 Aug 03 '14 at 00:01
  • This is from thinking in C++ v1. Sometimes, during the evaluation of an expression, the compiler must create temporary objects. These are objects like any other: they require storage and they must be constructed and destroyed. The difference is that you never see them – the compiler is responsible for deciding that they’re needed and the details of their existence. But there is one thing about temporaries: they’re automatically const. – user1443721 Aug 03 '14 at 00:03
  • That means they cannot be changed. const reference means something different: that you pass the object by reference, but it's not going to be changed within that function. Regarding the equal operator, I wonder if the compiler doesn't optimize it away, because the object to which it is applied is going to be destroyed, and no other variable depends on it. – Ashalynd Aug 03 '14 at 00:14
  • I add following code to the class. `code` X(const X& x) { cout << "Copy " << x.i << " to " << i << endl; i = x.i; } X operator=(const X& x) { cout << "Assigned " << x.i << " to " << i << endl; i = x.i; return *this; } `code` output from case 1: Assigned 2 to 1. Copy 2 to 1628966472. There is no output from case 3 and 4. Is there no copy action in these 2 cases? – user1443721 Aug 03 '14 at 02:44