是否有明确的副本

时间:2010-11-26 13:19:16

标签: c++ gcc explicit-constructor

我正在寻找这样的语法:

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

    Hugo GetRandomHugo()
    {
        Hugo hugo;
        hugo.value = rand();
                                  // this would fail:
                                  //    return hugo;

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

换句话说:我正在寻找一种显式的复制语法,以允许方法返回副本,即使我的复制构造函数是显式的。

我正在使用GCC 4.4.5。

非常感谢,

查理

3 个答案:

答案 0 :(得分:5)

您不能:按值返回是隐式副本构造。这里,返回尝试隐式复制显式复制构造的临时。

从8.5 / 12:

  

发生的初始化   参数传递,函数返回,   抛出异常(15.1),处理   例外(15.3),和   大括号括起初始化列表   (8.5.1)称为复制初始化   并且相当于以下形式:

     

T x = a;

答案 1 :(得分:3)

您可以通过明确的HugoCopy类来解决此问题,如下所示

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&) { ... }

现在应用以下语义

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
}

或者,您可以使用转换功能

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;
};

这依赖于C ++语言的一个微妙角落。因此,如果你使用它,你最好知道你正在做什么或者你不做:它首先调用HugoCopy上的转换函数(或者在第一种情况下,Hugo的构造函数)来获取{ {1}} / Hugo,然后使用该Hugo const&对象直接初始化目标Hugo对象。 GCC不喜欢这些代码,但Clang和Comeau / EDG根据上述语义接受它。

答案 2 :(得分:1)

return Hugo(hugo); 

这只会在返回之前创建一个额外的副本。然后,实际的return语句将获取该副本并将其重新复制。复制构造函数中的整个点是,只要我们或编译器需要复制对象,它就可以隐式使用。

如果您需要明确的语法,只需向类中添加Clone()Copy()函数,但它不能替换复制构造函数。

每次编译器需要复制一个对象时(例如,当通过值作为函数参数传递它时,或者从函数返回它时),它需要创建该对象的副本。您无法为编译器执行此操作,因为您没有在调用者和被调用者之间看到“转换”代码。您可以在被调用函数内部或其外部复制对象,但是您无法从被调用者的身体复制到调用者。只有编译器才能这样做,为了做到这一点,它需要能够随意复制对象 - 这是通过复制构造函数完成的。

相关问题