是否可以在main中选择构造函数而无需编写复制构造函数?

mmd*_*ger 8 c++ scope copy-constructor move-constructor c++11

真实的例子显然要长得多,但这总结了我的问题:

class Object
{
 int mInt1,mInt2;
 Object::Object();
 Object::Object(int param1);
 Object::Object(int param1, int param2);
};
Object::Object(){}
Object::Object(int param1):mInt1(param1){}
Object::Object(int param1, int param2):mInt1(param1),mInt1(param2){}
Run Code Online (Sandbox Code Playgroud)

然后在主要:

if (type1){
  Object instance(param1);
}
else{
  Object instance(param1,param2);
}
// do stuff with instance
Run Code Online (Sandbox Code Playgroud)

哎呦!这不起作用,实例超出了后续程序的范围.

Object instance;
if (type1){
  instance = Object(param1);
}
else{
  instance = Object(param1,param2);
}
// do stuff with instance
Run Code Online (Sandbox Code Playgroud)

但是现在我遇到了麻烦,因为我没有定义复制构造函数.我真的不想写一个拷贝构造函数,因为我的实际类有几十个成员,其中许多是非基本类型,可能需要更多的工作来复制.

具体来说,我得到了

main.cpp: error: use of deleted function ‘Object& Object::operator=(Object&&)’
         instance = Object(param1);
                  ^
note: ‘Object& Object::operator=(Object&&)’ is implicitly deleted because the default definition would be ill-formed:
Run Code Online (Sandbox Code Playgroud)

Que*_*onC 6

处理不可复制对象的通用方法是将其抛入unique_ptr(或auto_ptr,具体取决于您的编译器).

  std::unique_ptr<Object> instance;

  if (type1) {
    instance.reset(new Object(i));
  }
  else {
    instance.reset(new Object(i, j));
  }
Run Code Online (Sandbox Code Playgroud)

在这里使用原始指针确实不安全,因为一旦你开始处理异常或任何有趣的代码路径,就会担心泄漏.相信我,在100%的情况下,如果你把它放在unique_ptr中,你将会有更少的工作和代码行来处理.


最佳解决方案是重新设计Object的构造函数,因为绕过不可复制性可能会使对象处于非法状态.通常,如果编译器认为有必要,您希望保留不可复制性.但是,我们没有这里的细节来充实这样的解决方案.


Luc*_*ian 5

如果您不想动态分配,那么您可以使用Initialize函数:

class Object
{
 int mInt1,mInt2;
 Object::Object();
 Object::Initialize();
 Object::Initialize(int param1);
 Object::Initialize(int param1, int param2);
};
Object::Object(){Initialize();} //call the empty Initialize for nice coding...:)
Object::Initialize(){  }
Object::Initialize(int param1){ mInt1(param1); }
Object::Initialize(int param1, int param2){ mInt1(param1);mInt1(param2);}
Run Code Online (Sandbox Code Playgroud)

然后您可以使用initialize来选择类型.

Object instance;
if (type1){
  instance.Initialize(param1);
}
else{
  instance.Initialize(param1,param2);
}
Run Code Online (Sandbox Code Playgroud)