# C++ constructor question

This topic is 2849 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So we have this class "SimpleImage" that uses copy-on-write semantics. In a couple places in code, there is this: SimpleImage safeCopy = SimpleImage(some3rdPartyHandle); Now the thought is that this should take an image from a 3rd party library, and attach it to a temporary SimpleImage class. Then, upon construction of "safeCopy", we should get a unique copy because we can't reliably track reference count on images from 3rd parties. Point being, we want a unique copy of the image data. This would work... if it created a temporary SimpleImage object! Instead it is exactly (and I checked the assembly - and this is in debug build!) the equivalent of writing SimpleImage safeCopy(some3rdPartyHandle); which only attaches it and we don't get our unique copy. It doesn't even bother to build our temporary object at all! We have to do this instead: SimpleImage tempCopy(some3rdPartyHandle); SimpleImage safeCopy(tempCopy); or this will work too SimpleImage safeCopy; safeCopy = SimpleImage(some3rdPartyHandle); My question though is why? This is in MSVC2008 - is this correct c++ or a mistake in the compiler? That is.. the fact that it skips making the temporary altogether even in debug build?

##### Share on other sites
MSVC is behaving correctly. The relevant portion of the standard is section 8.5.

##### Share on other sites
:/ No standard to look at. Would it be legal for you or someone to quote the relevant text?

##### Share on other sites
IIRC, assignment and copy constructor may be used interchangably where appropriate.

##### Share on other sites
This goes into the same question. The gist of it is that

T x = a;

and

T x(a);

are mostly equivalent, except when used with explicit constructors, in which case only the latter succeeds.

##### Share on other sites
The first form also requires an accessible copy constructor (even though compilers should normally optimize away actual copying).

##### Share on other sites
Can't you just make a function that returns the copy?

##### Share on other sites
Quote:
 Original post by popsoftheyearNo standard to look at.

current draft from the WG21 website.

##### Share on other sites
Quote:
 Original post by d00fusThis goes into the same question. The gist of it is thatT x = a;and T x(a);are mostly equivalent, except when used with explicit constructors, in which case only the latter succeeds.

My point was that it turned out that

T x = T(a); // or T x(T(a));

and

T x(a);

were coming out to be the same. I had expected the first one to create a temporary T, and it didn't.
Quote:
 Original post by jwezorekCan't you just make a function that returns the copy?

Yup - but I was curious about the not-creating-a-temporary thing just in case it ever matters again in the future.

##### Share on other sites
If your copy constructors have normal semantics (not called for side-effects), then it should never matter if they are actually called or not.

With GCC you can force it to not optimize away those copies with -fno-elide-constructors. No idea how to achieve it with VC++.

##### Share on other sites
Maybe I'm missing something, but couldn't you just make SimpleImage automatically copy when constructed with a third-party handle? Is there ever a time when you don't want it to do that?

##### Share on other sites
Quote:
 Original post by theOcelotMaybe I'm missing something, but couldn't you just make SimpleImage automatically copy when constructed with a third-party handle? Is there ever a time when you don't want it to do that?

For our situation, almost always...

As a side note here's what the problem:
- 20 yr old code
- 3 different image libs, all 3rd party and very old
- Proprietary image lib desired (there is good reason for this)
- How to do all this incrementally?
- Main SimpleImage class wants to use proprietary stuff
- But it can use 3rd party stuff (keyword here is incrementally), but we don't want the performance penalty of making copies of potentially huge images hundreds of times a second. We can't replace code every where at once.
- As we remove dependance on 3rd party stuff and add functionality to proprietary lib, code that uses SimpleImage class already works.

That's it in a nutshell. 3rd party image handles from multiple image libs are scattered all over (in fact many of them are public class members!! And these handles tend to be either integers that mean "something" to the library, or a direct pointer!). So simultaneously we're trying to make the code safer as well - and it's really nasty at places. All the while this all has to be done on the side while we add features according to requirements from boss's boss. As an example, in one class, by replacing 3rd party stuff with our own over the last couple years (plus some other refactoring to a small extent), the line count for the class has gone from 25,000 to just over 10,000.

##### Share on other sites
So you need a separate function to create the copy of the data.

SimpleImage x = SimpleImage::copy(handle); //this is a normal thing to doSimpleImage x = SimpleImage(handle); //being different fromSimpleImage x(handle); //is not normal semantics

##### Share on other sites
Hang on, you said that this class uses copy-on-write. But none of the code you posted tries to write to it in any way. Shouldn't that mean that none of your examples make a copy?
Wouldn't you specifically need to call a function that has the exact purpose of performing a deep copy, if you want an actual copy?

Did you go wrong somewhere in your description, or have I understood wrong?

##### Share on other sites
Quote:
 Original post by popsoftheyearMy point was that it turned out thatT x = T(a); // or T x(T(a));andT x(a);were coming out to be the same. I had expected the first one to create a temporary T, and it didn't.

My understanding of the standard is that

T x = a;

is semantically equivalent to

T x = T(a);

which is likewise equivalent to

T x(T(a));

However, an implementation is free to (and almost certainly will) optimise out the temporaries. The following section of the standard I think specifies this:

Quote:
 From section 8.5:Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is an rvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization. In certain cases, an implementation is permitted to eliminate the copying inherent in this direct-initialization byconstructing the intermediate result directly into the object being initialized; see 12.2, 12.8.(emphasis mine)

##### Share on other sites
Quote:
Original post by popsoftheyear
Quote:
 Original post by theOcelotMaybe I'm missing something, but couldn't you just make SimpleImage automatically copy when constructed with a third-party handle? Is there ever a time when you don't want it to do that?

For our situation, almost always...

As a side note here's what the problem:
- 20 yr old code
- 3 different image libs, all 3rd party and very old

It sounds like you're already wrapping the APIs, though. Isn't the purpose of that wrapping to make it so that you can swap them for ones that behave better? :)