C++ 能否在C+;中关闭默认副本构造+;?

C++ 能否在C+;中关闭默认副本构造+;?,c++,compiler-construction,constructor,C++,Compiler Construction,Constructor,我不喜欢复制构造。我写了太多次了 void MyFunc(MyClass val) 而不是 void MyFunc(const MyClass& val) 并且不得不花费数小时调试指针周围的bug,这些指针在传递值克隆的析构函数中被删除,或者发现速度减慢,因为每次调用MyFunc时我都复制MyClass的每个成员 所以我不想允许复制构造函数 我知道你可以在每个班级的基础上用 private: MyClass(const MyClass&) 但我不想在每节课上都这么做

我不喜欢复制构造。我写了太多次了

void MyFunc(MyClass val)
而不是

void MyFunc(const MyClass& val)
并且不得不花费数小时调试指针周围的bug,这些指针在传递值克隆的析构函数中被删除,或者发现速度减慢,因为每次调用MyFunc时我都复制MyClass的每个成员

所以我不想允许复制构造函数

我知道你可以在每个班级的基础上用

private:
    MyClass(const MyClass&)
但我不想在每节课上都这么做


默认情况下,是否有编译器开关关闭复制构造?除了内置类型和指针之外,我是否有理由允许在任何其他对象上进行复制构造?(同样的问题也适用于复印作业)

没有神奇的开关。你只是犯了编程错误,想要改变语言。如果在堆上分配内存,则必须(或至少应该)重写默认的复制构造函数并处理该动态内存。或者,您可以使用一些现成的类,如std::vector或
std::auto_ptr
std::unique_ptr
在C++11中)

默认情况下,是否有编译器开关关闭复制构造

,我真的希望没有。幸运的是,据我所知,情况确实如此


除了内置类型和指针之外,我是否有理由允许在任何其他对象上进行复制构造

当然。例如,为类型赋予值语义,并将类的不同实例视为同一概念实体。在这种情况下,创建副本是一件非常方便的事情

另一方面,如果您想拥有一个不可复制的类(有这样的用例),您可以将复制构造函数声明为
private
(如您自己所建议的),或者在C++11中,将其标记为deleted:

关于你写的东西:

有太多次,我编写了
void MyFunc(MyClass-val)
而不是
void MyFunc(const MyClass&val)
,不得不花费数小时调试bug

我知道你可能会犯错误,但你必须从中吸取教训。您还可以编写一个普通函数,如下面的
foo()

void foo(int x) { x++; }
然后发誓几个小时,试图弄明白为什么当你把一个值为
3
的变量作为参数传递时,调用返回后该变量的值不是
4
。哦,您忘了添加参考符号:

void foo(int& x) { x++; }
//          ^
现在,这就是为什么需要一个编译器选项,使引用传递成为默认值的原因吗?不是真的。这将是改变语言规则的一个选择

想象一下,如果你的编译器真的有一个你想要的开关,并且有一天你会将你的程序发送给其他没有使用这个开关的人,那么会发生什么情况:他们会花多少时间调试它以找出问题所在


我的建议是从经验中学习,努力使你的阅读和写作技能适应标准语言,而不是相反

我要做的是在类中声明copy-ctor,但从不在任何地方定义它。如果我编写的代码使用复制向量,那么我会从链接器中得到一个未定义的符号。

std::vector
。你能在没有复制构造(或移动构造)的情况下使用它吗?“有没有理由我应该允许复制构造…?”是的,所以你可以复制构造和复制指定对象。在C++11中,也可以说
MyClass(MyClass const&)=delete。如果您像OP在问题中提到的那样将复制构造函数声明为私有,则会出现编译错误,这甚至更好。此外,如果您的编译器省略对复制构造函数的调用,我不确定这是否会起作用。我感谢您的回答。你认为现实生活中的编译器切换是个坏主意,所以我认为这个问题只是学术性的,但是——复制构造函数仍然应该是你必须选择加入的东西(通过在类头中明确声明它们为公共的),而不是选择退出。如果你想要一个类的副本,而这个类的数据可以随意处理和销毁,那么它们显然很有用,但是pass by ref/pass by const ref似乎不太容易出现错误,性能更高,更容易理解。@BenWalker:我的只是一个类比。也许pass-by-ref vs-pass-by-value不是最好的例子,但是复制构造实际上是大多数时候您想要的东西,而不是不想要的东西。价值语义学非常重要。没有副本构造函数会迫使您每次都通过引用传递。标准容器不是这样工作的。但是,即使假设(纯粹凭想象)默认情况下抑制复制构造函数是可取的,这种改变也会带来向后兼容性方面的巨大问题,破坏数十亿现有程序。
void foo(int& x) { x++; }
//          ^