454,371 Members | 1,495 Online
+ 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 Vector {}; template class VectorView: public Vector > { Ref r; public: VectorView() {} operator const Ref &() const { return r; } operator Ref &() { return r; } }; template class DenseVector: public Vector > { public: DenseVector() {} DenseVector(const DenseVector &rhs) {} VectorView > operator()(int from, int to) { return VectorView >(); } }; int fun(const DenseVector &x) { return 1; } int main() { DenseVector x, y; DenseVector &w = x(1,3); // (1) DenseVector 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
5 Replies

 P: n/a Alexander Stippler wrote: int main() { DenseVector x, y; DenseVector &w = x(1,3); // (1) DenseVector 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 x, y; DenseVector &w = x(1,3); // (1) DenseVector 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 x, y; DenseVector &w = x(1,3); // (1) DenseVector 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 x, y; DenseVector &w = x(1,3); // (1) DenseVector 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 &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 x, y;> DenseVector &w = x(1,3); // (1)> DenseVector 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 &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.