在 C++ 中使用隐式转换进行复制初始化

2022-01-18 00:00:00 initialization c++
class Foo {
  public:
    Foo(float b) {}
};

class Bar {
  public:
    Bar(Foo foo) {}
};

int main(int argc, char *argv[]) {
    Bar b1(3.0f);  // accept, one implicit convertion happens there.
    Bar b2 = 3.0f;  // error: no viable conversion from 'float' to 'Bar'
    return 0;
}

为什么第二个表达式编译失败?我希望它会调用与第一个表达式相同的转换构造函数.

Why does the second expression fail to compile? I expected that it would call the same converting constructor as same as the first expression.

推荐答案

From [dcl.init]:

From [dcl.init]:

否则(即,对于剩余的复制初始化情况),用户定义的转换序列可以将从源类型转换为目标类型或(当转换函数使用)对其派生类进行枚举,如 13.3.1.4 中所述,最好的一个是通过重载决议 (13.3) 选择.

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).

我们可以调用用户定义的从源类型直接到目标类型的转换.也就是说,如果我们有 Bar(float),我们会考虑那个构造函数.但是,在这种情况下,我们的候选对象只是 Bar(Foo ),它不采用 float.

We can invoke a user-defined conversion that is from the source type directly to the target type. That is, if we had Bar(float ), we would consider that constructor. However, in this case, our candidate is simply Bar(Foo ), which does not take a float.

您可以进行零次或一次用户定义的转换.在直接初始化的情况下,我们只需调用 Bar(Foo ),它会调用一个用户定义的转换 (float --> Foo).在复制初始化的情况下,我们正在寻找从 float(源类型)一直到 Bar(目标类型)的转换序列,这将涉及 两个 用户定义的转换(float --> FooFoo --> Bar),因此出现错误.

You are allowed zero or one user-defined conversion. In the direct-initialization case, we simply call Bar(Foo ) which invokes one user-defined conversion (float --> Foo). In the copy-initialization case, we are looking for a conversion sequence from float (the source type) all the way to Bar (the destination type), which would involve two user-defined conversions (float --> Foo, Foo --> Bar), hence the error.

相关文章