开发者

Is there a explicit copy

开发者 https://www.devze.com 2023-01-26 21:23 出处:网络
I\'m looking for a syntax like this: class Hugo { Hugo(); explicit Hugo( const Hugo& hugo ); Hugo GetRandomHugo()

I'm looking for a syntax like this:

class Hugo
{
    Hugo();
    explicit Hugo( const Hugo& hugo );

    Hugo GetRandomHugo()
 开发者_StackOverflow社区   {
        Hugo hugo;
        hugo.value = rand();
                                  // this would fail:
                                  //    return hugo;

        return Hugo(hugo);        // explicit copy!!
    }
};

In other words: I'm looking for a explicit copy syntax, to allow methods to return a copy, even if my copy constructor is explicit.

I'm using GCC 4.4.5.

Thanks a lot,

Charly


You can't : a return by value is an implicit copy construction. Here, the return attempts to implicitly copy your explicitly copy-constructed temporary.

From 8.5/12 :

The initialization that occurs in argument passing, function return, throwing an exception (15.1), handling an exception (15.3), and brace-enclosed initializer lists (8.5.1) is called copy-initialization and is equivalent to the form :

T x = a;


You can work around this by having an explicit HugoCopy class like the following

class HugoCopy;
class Hugo {
public:
    Hugo() { ... }  
    Hugo(HugoCopy const&);
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }

    Hugo const& hugo;
};

Hugo::Hugo(HugoCopy const&) { ... }

Now the following semantics apply

Hugo a;
Hugo b = a; // forbidden
Hugo c(a); // allowed
Hugo d = HugoCopy(a); // allowed

Hugo f() {
  Hugo a;
  return a; // forbidden
  return HugoCopy(a); // allowed
}

Alternatively, you can use a conversion function

class Hugo {
public:
    Hugo() { ... }  
    explicit Hugo(Hugo const&) { ... }
};

struct HugoCopy { 
    HugoCopy(Hugo const& hugo) 
      :hugo(hugo)
    { }
    operator Hugo const&() { return hugo; }

private:
    Hugo const& hugo;
};

This relies on a subtle corner of the C++ language. So if you use this, you better know what you're doing or you don't do it: It first calls the conversion function on HugoCopy (or in the first case, the constructor of Hugo) to get a Hugo / Hugo const&, and then it direct initializes the destination Hugo object with that Hugo object. GCC doesn't like the code, but Clang and Comeau/EDG accept it according to the above semantics.


return Hugo(hugo); 

this just creates one additional copy before returning. The actual return statement then takes that copy and copies it again. The entire point in the copy constructor is that it can be used implicitly, whenever we or the compiler need an object copied.

If you you want an explicit syntax, you can just add a Clone() or Copy() function to the class, but it can't replace the copy constructor.

Every time the compiler needs to copy an object (for example when passing it by value as a function parameter, or when returning it from a function), it needs to create a copy of the object. There is no way that you can do it for the compiler, because you don't see the "transition" code between caller and callee. You can copy the object around inside the called function, or outside it, but you have no way of copying from the callee's body to the caller. Only the compiler can do that, and in order to do that, it needs to be able to copy the object at will -- which is done through the copy constructor.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号