调用隐式删除的副本构造函数 [英] Call to implicitly deleted copy constructor

查看:122
本文介绍了调用隐式删除的副本构造函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下设置:

class MyClass {
 public:
  static MyClass Clone(const MyClass& other) { 
    return MyClass(other, 10);
  }

  static MyClass CreateNormal(int x, int y) {
    return MyClass(int x, int y);
  }

  // There are a few more factory functions.

 private:
  // Constructor 1
  MyClass(int x, int y) : b_(x, y) {}

  // Constructor 2
  MyClass(const MyClass& other, int c) : b_(other.b_, c) {}

  // And a lot more constructors.


  // NotMyClass has its copy constructor deleted.
  NotMyClass b_;
}

int main() {
  MyClass A(1,2);

  MyClass B = MyClass::Clone(A); // ERROR
}

是否有一种无需修改 NotMyClass 即可解决此问题的方法?发生错误是因为 MyClass 的副本构造函数被隐式删除.有没有一种方法可以使用std :: Move()解决此问题?

Is there a way to get around this without modifying NotMyClass? The error happens because the copy constructor of MyClass is implicitly deleted. Is there a way I can use std::Move() to solve this?

我无法删除工厂函数,因为实际的类具有许多构造函数,并且需要工厂函数才能清楚和理解.

I cannot remove the factory functions as the actual class has many constructors and the factory functions are needed for clarity and understanding.

推荐答案

假定c ++ 11标准的可用性,您可以延长factory方法返回的右值引用的生存期,而不用像构造一个新对象那样所以:

Assuming the availability of the c++11 standard, you could extend the lifetime of the rvalue reference returned by the factory method instead of constructing a new object, like so:

MyClass   A(1, 2);
MyClass&& B = MyClass::Clone(A);

附录:如patatahooligan在下面的评论中所述,在您的 MyClass :: Clone 版本本身中,可能存在复制构造函数调用.可以/需要将其重写为

Addendum: As noted by patatahooligan in a comment below, there might be a copy constructor invocation in your version of MyClass::Clone itself. This can/needs to be rewritten to

MyClass MyClass::Clone(const MyClass& other) {
    return {other, 10};
}

一旦C ++ 17附带了强制复制删除功能,所有这些都将是完全不必要的,因此您可以期待.

All of this will be completely unecessary once C++17 comes with mandatory copy-elision comes around, so you can look forward to that.

在C ++ 03中,尽管解决方案更长且需要更多代码,但仍然有可能达到期望的结果.我提供了两种选择:

In C++03 it is still possible to achive the desired outcome albeit the solutions are longer and require more code. I offer two alternatives:

我建议不要使用一组静态方法,而建议使用tag-dispatch来表示不同的构造方法含义.这可以通过使用类型参数重载构造函数来实现,这些参数具有明确的名称,但不包含任何数据.

Instead of creating a set of static methods, I would advise for using tag-dispatch to signal different constructor meanings. This works by overloading the constructor with type arguments which have clear names but hold no data.

struct clone_tag {};
class MyClass {
public:

    MyClass(int x, int y) : b_(x, y) {}
    MyClass(const MyClass& self, clone_tag) : b_(self.b_, 10) {}
private:

    NotMyClass b_;
};

int main() {
    MyClass   A(1, 2);
    MyClass   B(A, clone_tag());
}

这甚至可以扩展到真正的工厂模式,在这种模式下,工厂的建造和对象的最终构造是分开的.显然,这需要更多的时间来设置,但是可以提高代码质量,具体取决于不同构造函数路径的实际数量.

Or this could even go as far as a genuine factory pattern, where the building the factory and final construction of the object is seperated. This clearly needs more time to set up but could improve code quality, depending on the actual number of different constructor paths.

class MyClass {
public:
    struct Clone {
        Clone(const MyClass& self) : self(self) {}
        const MyClass& self;
    };
    struct Init {
        Init(int x, int y) : x(x), y(y) {}
        int x, y;
    };

    MyClass(Init i) : b_(i.x, i.y) {}
    MyClass(Clone c) : b_(c.self.b_ , 10) {}
private:
    MyClass(const MyClass& other, int c) : b_(other.b_, c) {}

    NotMyClass b_;
};


int main() {
    MyClass   A = MyClass::Init(1, 2);
    MyClass   B = MyClass::Clone(A);
}


第二个想法是,我意识到给出三个不同的选择可能会导致比简短的答案(更不准确)引起更多的混乱.因此,尽管这只是有关您实际代码库的猜测工作,但我尝试按所需的重构工作顺序列出它们.


On second thought I realize that giving three different alternatives could cause more confusion than a short answer which is less precise. I therefore tried to list them in order of needed refactoring work although this is only guess work about your real code base.

这篇关于调用隐式删除的副本构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆