【问题标题】:Copy initialization with conversion operator使用转换运算符复制初始化
【发布时间】:2020-03-31 15:09:03
【问题描述】:

copy_initialization中有代码

struct A 
{
  operator int() { return 12;}
};

struct B 
{
  B(int) {}
};
int main()
{
 ....
    A a;
    B b0 = 12;
//    B b1 = a; //< error: conversion from 'A' to non-scalar type 'B' requested
    B b2{a};        // < identical, calling A::operator int(), then B::B(int)
    B b3 = {a};     // <
    auto b4 = B{a}; // <
}

现在的问题是

  • 对于 b2,直接初始化如何工作?可以直接初始化调用转换算子吗?
  • 为什么 b1 的复制初始化失败?应该将 A 隐式转换为 int 并且可以调用 B 的构造函数。
  • b3 也是复制初始化,但它可以工作。为什么会这样?

【问题讨论】:

  • 一次只能进行一次隐式用户转换,B b1 = a;需要2次

标签: c++ initialization


【解决方案1】:

这很简单:隐式可转换性(对于用户定义的类型)不是 C++ 中的 传递 属性。也就是说,虽然A 可转换为int,并且int 可转换为B,但这本身意味着A 可转换为B。从AB 没有有效的隐式转换序列,所以A 不能转换为B

复制初始化需要初始化表达式的类型和被初始化的类型之间的隐式转换。由于A 不能转换为Bb1 无法编译。

任何时候您将{} 视为此类初始化的一部分,这意味着它所应用的对象将经历某种形式的列表初始化,这是与其他形式的初始化不同的过程。

b2 不执行“直接初始化”。它执行直接 list 初始化,这是列表初始化的两种形式之一。在这种情况下,列表初始化的规则最终归结为对B 的构造函数集使用重载决议。有一个B 的构造函数可以用A 调用,因为该调用可以通过将A 隐式转换为int 来实现。

b3 不是“复制初始化”;是拷贝list初始化,和“拷贝初始化”完全没有关系。 Copy-list-initialization 与 direct-list-initialization 完全相同,只有两个例外,这两个例外都不适用于这种情况。所以它和b2做同样的事情。

【讨论】:

  • 某些隐式可兑换性确实过境。例如,A 可转换为intint 可转换为bool,因此A 可转换为bool
  • @eerorika:已更正。
  • 感谢妮可澄清事情。
猜你喜欢
  • 2019-11-03
  • 2012-03-25
  • 2017-05-31
  • 2011-10-30
  • 2012-12-08
  • 2019-12-15
  • 2021-07-03
  • 2010-12-20
  • 2014-03-16
相关资源
最近更新 更多