在 C++ 中选择可行的构造函数时,何时不考虑用户定义的转换序列?
When are user-defined conversion sequences not considered for selecting viable constructors in C++?
我在C++标准草案N4582中看到如下文字:
[over.best.ics/4] However, if the target is
(4.1) the first parameter of a constructor or
(4.2) the implicit object parameter of a user-defined conversion function
and the constructor or user-defined conversion function is a candidate by
(4.3) 13.3.1.3, when the argument is the temporary in the second step of a class copy-initialization, or
(4.4) 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases),
user-defined conversion sequences are not considered.
我对加粗部分一头雾水,不知道怎么理解。我写了下面的程序:
#include <iostream>
using namespace std;
struct A {
A(int) {}
operator int() {cout << "user-defined conversion" << endl; return 0;}
A(A&) {} //prevent default copy
};
int main()
{
A a = A(0);
}
在g++5.3.0下运行良好,输出“user-defined conversion”,表示发生了用户自定义转换。当然,可以解释为临时A(0)不是copy-initialization的结果。接下来我将程序更改为:
#include <iostream>
using namespace std;
struct A {
A(int) {}
operator int() {cout << "user-defined conversion" << endl; return 0;}
A(A&) {} //prevent default copy
};
A foo() {return A(0);}
int main()
{
A a = foo();
}
现在 foo() 的值是从 A(0) 初始化的临时副本,但程序仍然有效。为什么会这样?
您可以阅读 [dcl.init]/17 以了解实际的标准语。这里的 "second step" 是指从不相关类型的 b
中复制初始化 class 类型 A
的变量。在这种情况下,复制初始化分两步进行:
- 第 1 步:将
b
隐式转换为 A
。如果为此调用转换构造函数,它会创建一个临时的 A
.
- 第 2 步:然后根据转换结果初始化
A
变量。 (在理智的 classes 中,这通常被省略。)
这句话的意思是您不会在第二步中进行用户定义的转换。
例如,您的 A
、A a = 0;
。在第一步中,您从 0
创建一个 A
临时文件。在第二步中,您尝试使用该临时值初始化 a
- 不使用用户定义的转换。那失败了,因为 A
构造函数都不可行。
只有 2 个 ctors,一个引用现有对象(非临时对象),一个引用 int。
您的代码生成(带有附加消息):
int ctor
user-defined conversion
int ctor
user-defined conversion
int ctor
首先是foo
里面的构造。
第二个是由于返回值不能像你阻止的那样通过复制构造,所以编译器将构造的值转换为int
。
第三个是因为它使用带有 int
的构造函数来构建返回值。
第四个(同第二个)由于返回值不能用来构造a
,所以将其转换为int
.
第五个是因为它随后使用采用 int
的构造函数来构建 a
。
我在C++标准草案N4582中看到如下文字:
[over.best.ics/4] However, if the target is
(4.1) the first parameter of a constructor or
(4.2) the implicit object parameter of a user-defined conversion function
and the constructor or user-defined conversion function is a candidate by
(4.3) 13.3.1.3, when the argument is the temporary in the second step of a class copy-initialization, or
(4.4) 13.3.1.4, 13.3.1.5, or 13.3.1.6 (in all cases),
user-defined conversion sequences are not considered.
我对加粗部分一头雾水,不知道怎么理解。我写了下面的程序:
#include <iostream>
using namespace std;
struct A {
A(int) {}
operator int() {cout << "user-defined conversion" << endl; return 0;}
A(A&) {} //prevent default copy
};
int main()
{
A a = A(0);
}
在g++5.3.0下运行良好,输出“user-defined conversion”,表示发生了用户自定义转换。当然,可以解释为临时A(0)不是copy-initialization的结果。接下来我将程序更改为:
#include <iostream>
using namespace std;
struct A {
A(int) {}
operator int() {cout << "user-defined conversion" << endl; return 0;}
A(A&) {} //prevent default copy
};
A foo() {return A(0);}
int main()
{
A a = foo();
}
现在 foo() 的值是从 A(0) 初始化的临时副本,但程序仍然有效。为什么会这样?
您可以阅读 [dcl.init]/17 以了解实际的标准语。这里的 "second step" 是指从不相关类型的 b
中复制初始化 class 类型 A
的变量。在这种情况下,复制初始化分两步进行:
- 第 1 步:将
b
隐式转换为A
。如果为此调用转换构造函数,它会创建一个临时的A
. - 第 2 步:然后根据转换结果初始化
A
变量。 (在理智的 classes 中,这通常被省略。)
这句话的意思是您不会在第二步中进行用户定义的转换。
例如,您的 A
、A a = 0;
。在第一步中,您从 0
创建一个 A
临时文件。在第二步中,您尝试使用该临时值初始化 a
- 不使用用户定义的转换。那失败了,因为 A
构造函数都不可行。
只有 2 个 ctors,一个引用现有对象(非临时对象),一个引用 int。
您的代码生成(带有附加消息):
int ctor
user-defined conversion
int ctor
user-defined conversion
int ctor
首先是foo
里面的构造。
第二个是由于返回值不能像你阻止的那样通过复制构造,所以编译器将构造的值转换为int
。
第三个是因为它使用带有 int
的构造函数来构建返回值。
第四个(同第二个)由于返回值不能用来构造a
,所以将其转换为int
.
第五个是因为它随后使用采用 int
的构造函数来构建 a
。