加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 复制初始化和直接初始化的混乱

发布时间:2020-12-16 06:51:20 所属栏目:百科 来源:网络整理
导读:考虑简单陈述(摘自 Is there a difference in C++ between copy initialization and direct initialization?): A c2 = A(); This statement value-initializes a temporary and then copies that value into c2 (Read 5.2.3/2 and 8.5/14). This of course
考虑简单陈述(摘自 Is there a difference in C++ between copy initialization and direct initialization?):

A c2 = A();

This statement value-initializes a temporary and then copies that
value into c2 (Read 5.2.3/2 and 8.5/14). This of course will require a
non-explicit copy constructor (Read 8.5/14 and 12.3.1/3 and
13.3.1.3/1)

[注意上面的段落中的大胆句子] – >我的问题是为什么?

现在考虑这段代码:

class B {};
struct A 
{
  A(B const&) {}
  A(A const&) = delete;
  //A(A const&); //delete above statement and uncomment this statement,//and everything works,even though there in no body of copy constructor Oo
};

A a2 = B();    //error since there is no copy constructor oO

为什么复制初始化需要复制构造函数的存在,即使它在某些时候不需要,如上面的代码所示

请再请一件事:

While direct initialization has all constructors available to call,
and in addition can do any implicit conversion it needs to match up
argument types,copy initialization can just set up one implicit
conversion sequence
.

[注意以下段落中的粗体]

这是否意味着直接初始化可以访问所有构造函数并且可以执行隐式转换序列,而复制初始化所有可以做的是执行隐式转换序列? .我的意思是,直接初始化中的隐式转换与复制初始化中的隐式转换序列不同?

解决方法

评估规则

A a1 = B();   // (1) copy-initialization
A a2 = {B()}; // (2) copy-initialization
A a3{B()};    // (3) direct-initialization

来自[dcl.init]/17:

— If the initializer is a (non-parenthesized) braced-init-list,the object or reference is list-initialized (8.5.4).
— […]
— If the destination type is a (possibly cv-qualified) class type:

  • 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. […]
  • 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). […] 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.

对于a2和a3,初始化程序是braced-init-list,所以我们只进行列表初始化.这最终称为B const&构造函数.

对于a1,第一个子项不适用 – 因为源类型(B)不是目标类型(A)的相同或派生类.因此,我们进入第二个子项目,涉及考虑转换函数.有一个(A(B const&))所以我们有效地重写了表达式

A a1_new{A{B{}}};

现在通常,这个额外的副本将被省略.但是你明确禁止它,所以代码无法编译.

至于为何分化?我不知道.似乎复制初始化应该只是直接初始化的语法糖.毕竟,在大多数情况下,它是……

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读