Topic: [Q} Rationale behind C++ rule on copying temporary object to
Author: brok@rubikon.pl (Bronek Kozicki)
Date: Sat, 16 Oct 2004 18:29:33 GMT Raw View
Marcel Loose wrote:
> In short, what this rule says is that, when you pass a temporary object to a
> (member) function that expects a const reference, the temporary should be
> copy-constructible. To me, this is counter-intuitive. One of the reasons (I
> was taught) to use const references in a function's parameter list is to
> allow passing of temporary objects, because temporary objects are
> effectively const. This rule obviously forbids this use for non-copyable
> objects.
Temporary objects are not "effectively const". See below, well-formed code:
struct A
{
void f() {} // non-const!
};
A a() {return A();}
int main()
{
a().f();
}
> So, if I understand it correctly, if I have a class that is non-copyable, I
> am you are forced to first create an instance of that class and then pass
> that instance to the function which may create a copy of that instance. What
> a waste of CPU cycles!. I don't get it. Anyone, please?
I think that you get it wrong. If you create variable, it's no longer
rvalue but lvalue, and second bullet does not apply. Copy is not
created, and reference (the one being parameter of function) is directly
bound to variable per first bullet of clause 8.5.3/5. Copy constructor
does not need to be available; you do not loose any extra CPU cycles
here. Following code is well-formed:
class B
{
B(const B&);
public:
B(){}
};
void f(const B&) {}
int main()
{
B b;
f(b);
}
On the other hand, if you create temporary (that is, rvalue) and pass it
to function, implementation is free to create copy of this temporary and
bound const reference (the one being parameter of function) to this
copy, per second bullet of said clause. However, this behaviour is
implementation defined - obviously compiler with strong optimisation
won't create this copy, thus you do not loose any extra CPU cycles.
However copy constructor needs to be available. Thus following code is
ill-formed:
class C
{
C(const C&);
public:
C(){}
};
void g(const C&) {}
int main()
{
g(C());
}
as well as following one:
class D
{
D(const D&);
friend D f();
public:
D(){}
};
D f() {return D();}
int main()
{
const D& d = f();
}
I understand your question as to why this behaviour is allowed at all;
sincerly, I do not know answer - I suppose that it's to give some
freedom to implementers. I'd like to know answer to your question, too
B.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html ]