有没有明确的副本

发布于 2024-10-04 04:30:01 字数 465 浏览 2 评论 0原文

我正在寻找这样的语法:

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

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

我正在使用海湾合作委员会4.4.5。

非常感谢,

查理

I'm looking for a syntax like this:

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

遗弃M 2024-10-11 04:30:01

你不能:按值返回是一种隐式复制构造。在这里,返回尝试隐式复制显式复制构造的临时对象。

从 8.5/12 开始:

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

T x = a;

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;

寄人书 2024-10-11 04:30:01

您可以通过使用如下所示的显式 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 的构造函数)来获取 Hugo / Hugo const&,然后使用该 直接初始化目标 Hugo 对象Hugo 对象。 GCC 不喜欢该代码,但 Clang 和 Comeau/EDG 根据上述语义接受它。

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.

邮友 2024-10-11 04:30:01
return Hugo(hugo); 

这只是在返回之前创建一个额外的副本。然后,实际的 return 语句获取该副本并再次复制它。复制构造函数的全部要点是,每当我们或编译器需要复制对象时,它都可以隐式使用。

如果您想要显式语法,只需向类添加 Clone()Copy() 函数即可,但它不能替换复制构造函数。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文