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