代码之家  ›  专栏  ›  技术社区  ›  Priyanka Mishra

为什么编译器提供默认的复制构造函数

  •  10
  • Priyanka Mishra  · 技术社区  · 15 年前

    我想知道为什么编译器提供默认的复制构造函数……这个想法背后的策略是什么。

    事先谢谢。

    10 回复  |  直到 15 年前
        1
  •  26
  •   Community CDub    8 年前

    从一个相关(但不相同)的问题- Why don't C++ compilers define operator== and operator!=? :

    Stroustrup在“C++的设计和演化”(第114.1-复制控制)中谈到了默认复制构造函数:

    我个人认为不幸的是,复制操作是默认定义的,并且我禁止复制我的许多类的对象。但是,C++继承了它的默认赋值,并复制了C的构造函数,它们经常被使用。

    因此,答案是,它不情愿地包含了Stroustrup与C的向后兼容性(可能是大多数C++疣的原因,但也可能是C++流行的主要原因)。

    出于我自己的目的,在我的IDE中,我用于新类的代码段包含私有赋值运算符和复制构造函数的声明,这样当我生成一个新类时,就不会得到默认赋值和复制操作-如果我希望编译器能够为我生成它们。

        2
  •  8
  •   Bill the Lizard    15 年前

    The C++ Programming Language ,第11.3.4节复制

    …对于默认复制构造函数具有正确语义的类型,我更喜欢依赖该默认值。它比我能写的任何东西都不冗长,人们应该理解默认值。此外,编译器知道缺省值及其可能的优化机会。此外,对于具有许多数据成员的类来说,手工编写memberwise copy非常繁琐且容易出错。

    基本上,我了解到,作为默认的复制构造函数,可以节省您的工作,避免您因单调乏味而出错,并通过消除手工优化代码的诱惑(让编译器来完成)来帮助优化代码。

        3
  •  6
  •   Stefano Borini    15 年前

    否则,当通过值传递实例时,编译器如何生成实例?

        4
  •  3
  •   JaredPar    15 年前

    我不知道为什么它最初是那样设计的。但作为一个用户,我可以说我为什么很高兴他们这么做。

    1. 如果使用所有的raii或pod类型,复制构造函数将做正确的事情。
    2. 复制建设者不需要思考或维护,他们只需要工作给定的1

    对于默认的赋值操作符,我也有同样的感觉。大多数人要么a)错误地定义了他们的copy constructor/equals运算符,要么未能对其进行维护。通过切换到RAII类型和删除手工编码的操作符/复制构造函数,我在C++代码中删除了很多错误。

        5
  •  3
  •   Richard Corden    15 年前

    几点:

    重要的是能够控制一个对象是否可以被复制。

    如果你不想复制一个对象,那么你可以声明拷贝构造函数是私有的(在C++中你可以说)。 =delete )这与您的建议是一致的,但是问题是简单地颠倒的,即,您可以预见这样一个问题:“为什么编译器在知道要做什么时不生成默认的复制构造函数?”

    这也将在C++0X中得到解决,因为我相信有一个 =default 允许您指定它的标志:

    class C {
    public:
      C (C const &) = default;
    };
    

    允许编译器实现复制构造函数的最佳版本是有益的。

    撇开易用性不谈,如今编译器能够选择最有效的方法来复制对象。例如,如果 知道这样做是安全的。

    有了您的建议,为了今天实现类似的优化,编译器需要分析构造函数主体,以验证它只不过是简单地复制所有成员。这不仅是不平凡的,而且通常只能在构造函数主体对 全部的 翻译单位。

    在C++ 0x中 =默认值 绕过这个。

    如果C++0x、编译器和静态分析工具开始生成关于“旧式隐式默认成员”的警告,我不会感到惊讶。

        6
  •  1
  •   Goz    15 年前

    节省你的时间?如果您有一个简单的类(如果您可以轻松地复制构造它的所有元素),那么就不需要编写一个。

        7
  •  1
  •   Paul Nathan    15 年前

    如果你有 struct 在C代码使用中,需要有一个默认的复制构造函数来保留C结构复制语义。

        8
  •  0
  •   Uri    15 年前

    我不知道“官方热线”是什么(我附近没有斯特拉斯特罗普的书),我相信会有人把它挖出来。

    但是,在大多数情况下,浅拷贝和默认初始化是“足够好的”,所以 对于编译器来说,提供它们比让developerExplicitly编写它们要好。

    如果开发人员编写了这个简单的复制构造函数,并且字段随后发生了更改,则由该用户来进行更改,如果他忘记了(例如,这些字段的构造方式是什么?).

    当确实需要做一些花哨的事情(如深度复制)时,只允许用户编写复制构造函数,这样可以减少这些错误的频率。

        9
  •  0
  •   njplumridge    15 年前

    我认为你是从错误的方向来的——如果编译器可以为每个类或结构编写一个完整和正确的“默认”复制构造函数,那么没有人会抱怨,是吗?问题是,编译器不能可靠地做到这一点,因此对于这些情况,您需要编写自己的,覆盖默认值。

        10
  •  0
  •   bobflux    15 年前

    因为C++不是垃圾收集,它迫使你跟踪所有的指针所有者,这实际上是不可能的,除非你通过使用大量的复制来简化问题,所以至少你知道谁拥有拷贝,顺便说一下,你的程序比垃圾收集程序慢。自动生成的复制构造器是棺材中的一颗钉子,它被放置在棺材中,以隐藏新的和删除的“地狱之洞”。