复制和直接初始化行为不同的动机是什么?

有点相关 为什么调用复制构造函数而不是转换构造函数?

初始化有两种语法,直接初始化和复制初始化:

There are two syntaxes for initialization, direct- and copy-initialization:

A a(b);
A a = b;

我想知道他们有不同定义行为的动机.对于副本初始化,涉及到一个额外的副本,我想不出那个副本有什么用途.由于它是临时副本,因此可以并且可能会对其进行优化,因此用户不能依赖它的发生-因此,额外的副本本身不足以引起不同的行为.那么……为什么?

I want to know the motivation for them having different defined behavior. For copy initialization, an extra copy is involved, and I can't think of any purpose for that copy. Since it's a copy from a temp, it can and probably will be optimized out, so the user can't rely on it happening - ergo the extra copy itself isn't reason enough for the different behavior. So... why?

推荐答案

由于它是临时副本,它可以并且可能会被优化

这里的关键字是可能.该标准允许但不要求编译器优化副本.如果某些编译器允许此代码(优化),而其他编译器拒绝它(未优化),这将是非常不一致的.

The keyword here is probably. The standard allows, but does not require, a compiler to optimize the copy away. If some compilers allowed this code (optimized), but others rejected it (non-optimized), this would be very inconsistent.

因此标准规定了一种一致的处理方式 - 每个人都必须检查复制构造函数是否可访问,无论他们是否使用它.

So the standard prescribes a consistent way of handling this - everyone must check that the copy constructor is accessible, whether they then use it or not.

这个想法是所有编译器都应该接受或拒绝代码.否则它将是不可移植的.

The idea is that all compilers should either accept the code or reject it. Otherwise it will be non-portable.

另一个例子,考虑

A a;
B b;

A a1 = a;
A a2 = b;

A 的复制构造函数是私有的时,允许 a2 而禁止 a1 同样是不一致的.

It would be equally inconsistent to allow a2 but forbid a1 when As copy constructor is private.

我们还可以从标准文本中看到,初始化类对象的两种方法本来是不同的(8.5/16):

We can also see from the Standard text that the two methods of initializing a class object were intended to be different (8.5/16):

如果初始化是直接初始化,或者如果是复制初始化,其中源类型的 cv 非限定版本与目标类相同或派生类,则考虑构造函数.枚举了适用的构造函数(13.3.1.3),并通过重载决议(13.3)选择最佳构造函数.调用如此选择的构造函数来初始化对象,使用初始化表达式或 expression-list 作为其参数.如果没有构造函数适用,或者重载决议不明确,则初始化格式错误.

If the initialization is direct-initialization, or if it is copy-initialization where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination, constructors are considered. The applicable constructors are enumerated (13.3.1.3), and the best one is chosen through overload resolution (13.3). The constructor so selected is called to initialize the object, with the initializer expression or expression-list as its argument(s). If no constructor applies, or the overload resolution is ambiguous, the initialization is ill-formed.

否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换序列被枚举为描述在 13.3.1.4 中,通过重载决议 (13.3) 选择最好的一个.如果转换无法完成或不明确,则初始化格式错误.以初始化表达式作为参数调用所选函数;如果函数是构造函数,则调用初始化目标类型的 cv 非限定版本的临时版本.临时是prvalue.然后根据上述规则,调用的结果(对于构造函数的情况是临时的)用于直接初始化作为复制初始化目标的对象.在某些情况下,允许实现通过将中间结果直接构造到正在初始化的对象中来消除这种直接初始化中固有的复制;见 12.2、12.8.

Otherwise (i.e., for the remaining copy-initialization cases), user-defined conversion sequences that can convert from the source type to the destination type or (when a conversion function is used) to a derived class thereof are enumerated as described in 13.3.1.4, and the best one is chosen through overload resolution (13.3). If the conversion cannot be done or is ambiguous, the initialization is ill-formed. The function selected is called with the initializer expression as its argument; if the function is a constructor, the call initializes a temporary of the cv-unqualified version of the destination type. The temporary is a prvalue. The result of the call (which is the temporary for the constructor case) is then used to direct-initialize, according to the rules above, the object that is the destination of the copy-initialization. In certain cases, an implementation is permitted to eliminate the copying inherent in this direct-initialization by constructing the intermediate result directly into the object being initialized; see 12.2, 12.8.

不同之处在于直接初始化直接使用构造类的构造函数.使用复制初始化时,会考虑其他转换函数,这些函数可能会产生一个必须被复制的临时函数.

A difference is that the direct-initialization uses the constructors of the constructed class directly. With copy-initialization, other conversion functions are considered and these may produce a temporary that has to be copied.

相关文章