By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
454,371 Members | 1,495 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 454,371 IT Pros & Developers. It's quick & easy.

copy constructor - optimized away or not?

P: n/a
The following code snippet (those of you who read my last postings
might be familiar with it ;-)):

//--------------------------------------------------------------------
template<class Impl>
class Vector {};

template<class Ref>
class VectorView: public Vector<VectorView<Ref> >
{
Ref r;
public:
VectorView() {}
operator const Ref &() const { return r; }
operator Ref &() { return r; }
};

template<class T>
class DenseVector: public Vector<DenseVector<T> >
{
public:
DenseVector() {}

DenseVector(const DenseVector<T> &rhs) {}

VectorView<DenseVector<T> >
operator()(int from, int to)
{ return VectorView<DenseVector<T> >(); }
};

int fun(const DenseVector<double> &x) { return 1; }

int main()
{
DenseVector<double> x, y;
DenseVector<double> &w = x(1,3); // (1)
DenseVector<double> z = x(1,3); // (2)
fun(x(1,3)); // (3)
return 0;
}
//--------------------------------------------------------------------

What we are not able to comprehend is what happens in the three marked
lines:
In (2) x(1,3) creates an object of type VectorView<...> and its member
r is actually copied into z.
In (1) and (3) no such copying takes place.
Perhaps someone could tell us in detail what's going on internally in
those lines. Does it have to to with the copy constructor optimization
allowed by the standard in 12.8(15).
And if yes why does e.g. gcc 4.0 treat the three cases differently?
The standard does not enforce this optimization. But can it be
guaranteed that in (1) and (3) there will be no copying and that there
will always be copying in (2)?

Thanks
Alex
Oct 30 '05 #1
Share this Question
Share on Google+
5 Replies


P: n/a
Alexander Stippler wrote:
int main()
{
DenseVector<double> x, y;
DenseVector<double> &w = x(1,3); // (1)
DenseVector<double> z = x(1,3); // (2)
fun(x(1,3)); // (3)
return 0;
}
//--------------------------------------------------------------------

What we are not able to comprehend is what happens in the three marked
lines:
In (2) x(1,3) creates an object of type VectorView<...> and its member
r is actually copied into z.
In (1) and (3) no such copying takes place.


In (1) you explicitly ask the compiler not to copy anything. `w` is a reference.

In (2) the compiler is allowed to optimise away the copy. I guess g++ was confused by the
fact that the type you return is different from the type you copy to.

In (3) you pass the new object to "fun" by reference, so again you explicitly ask it not
to copy.

You would understand your own code better if you had a simple example without all these
templates which only obscure the real problem.

--

Valentin Samko - http://www.valentinsamko.com
Oct 30 '05 #2

P: n/a
In <43***********************@authen.white.readfreene ws.net> Valentin
Samko wrote:
Alexander Stippler wrote:
int main()
{
DenseVector<double> x, y;
DenseVector<double> &w = x(1,3); // (1)
DenseVector<double> z = x(1,3); // (2)
fun(x(1,3)); // (3)
return 0;
}
//--------------------------------------------------------------------

What we are not able to comprehend is what happens in the three
marked lines: In (2) x(1,3) creates an object of type VectorView<...>
and its member r is actually copied into z. In (1) and (3) no such
copying takes place.
In (1) you explicitly ask the compiler not to copy anything. `w` is a
reference.

In (2) the compiler is allowed to optimise away the copy. I guess g++
was confused by the fact that the type you return is different from
the type you copy to.

In (3) you pass the new object to "fun" by reference, so again you
explicitly ask it not to copy.


But in (2) I pass the object by reference too. No difference to (3)
with respect to this.
You would understand your own code better if you had a simple example
without all these templates which only obscure the real problem.

Template code has different behavior in several areas. So I do not
want to understand it for non-template code and then recognize that
template code behaves diffent. And the templates do not add complexity
here. And in one place in the code they are not superfluous, but
essential to realize the Barton-Nackman-Trick.
--

Valentin Samko - http://www.valentinsamko.com

Oct 30 '05 #3

P: n/a
Alexander Stippler wrote:
DenseVector<double> x, y;
DenseVector<double> &w = x(1,3); // (1)
DenseVector<double> z = x(1,3); // (2)
fun(x(1,3)); // (3)
In (2) the compiler is allowed to optimise away the copy. I guess g++
was confused by the fact that the type you return is different from
the type you copy to.

In (3) you pass the new object to "fun" by reference, so again you
explicitly ask it not to copy.


But in (2) I pass the object by reference too. No difference to (3)
with respect to this.

I do not see any references in the (2) code path. What do you mean by "I pass the object
by reference too"?

--

Valentin Samko - http://www.valentinsamko.com
Oct 30 '05 #4

P: n/a
In <43***********************@authen.white.readfreene ws.net> Valentin
Samko wrote:
Alexander Stippler wrote:
DenseVector<double> x, y;
DenseVector<double> &w = x(1,3); // (1)
DenseVector<double> z = x(1,3); // (2)
fun(x(1,3)); // (3) In (2) the compiler is allowed to optimise away the copy. I guess
g++ was confused by the fact that the type you return is different
from the type you copy to.

In (3) you pass the new object to "fun" by reference, so again you
explicitly ask it not to copy.


But in (2) I pass the object by reference too. No difference to (3)
with respect to this.

I do not see any references in the (2) code path. What do you mean by
"I pass the object by reference too"?


The signature of fun is void fun(const DenseVector<double> &x), so
the argument is a const &. And the copy constructor for (2) expects
a const & too. Where am I wrong?
Oct 30 '05 #5

P: n/a
Alexander Stippler wrote:
> DenseVector<double> x, y;
> DenseVector<double> &w = x(1,3); // (1)
> DenseVector<double> z = x(1,3); // (2)
> fun(x(1,3)); // (3)
In (2) the compiler is allowed to optimise away the copy. I guess
g++ was confused by the fact that the type you return is different
from the type you copy to.

In (3) you pass the new object to "fun" by reference, so again you
explicitly ask it not to copy.

But in (2) I pass the object by reference too. No difference to (3)
with respect to this.

I do not see any references in the (2) code path. What do you mean by
"I pass the object by reference too"?

The signature of fun is void fun(const DenseVector<double> &x), so
the argument is a const &. And the copy constructor for (2) expects
a const & too. Where am I wrong?


1. Yes, you have a reference in the copy constructor, I missed that.

2. operator() returns object by value, this leads to one temporary (which may be optimised
away, this depends on implementation of operator ()).

3. this has nothing to do with the function "fun" as it is not called in (2).

4. In addition to a possible temporary, you are creating a new object "z" which will
contain a copy of that temporary.

--

Valentin Samko - http://val.samko.info
Oct 30 '05 #6

This discussion thread is closed

Replies have been disabled for this discussion.