我正在使用Visual Studio 2013,这就是我要弄清楚的:
#include <iostream>
#include <vector>
using namespace std;
class A
{
public:
int x = 1;
bool y = true;
A(int _x, bool _y) : x(_x), y(_y)
{
cout << "Constructor #1" << endl;
}
A(std::initializer_list<int> init_list)
{
cout << "Constructor #2" << endl;
}
};
int main(int argc, char** argv)
{
A Aobj1(10, false);
A Aobj2(20, "false");
A Aobj3{30, false};
A Aobj4{40, "false"};
return 0;
}
输出为:
Constructor #1 Constructor #1 Constructor #2 Constructor #1
构造函数#1的第一次调用很好
现在调用构造函数#1的Aobj2(int, string)
的第二种构造很奇怪。编译器如何使用字符串参数调用(int, bool)
构造函数? “假” bool
甚至不会转换为整数。
Aobj3
也可以。尽管initializer_list
的类型为int,但编译器由于进行了括号初始化而将其调用,并将布尔值转换为int。
这又一次让我感到困惑。我本来希望这是一个错误,因为不能将字符串转换为int(与bool一样),并且还希望编译器正在调用initializer_list
构造函数,因为它是初始化初始化。但是编译器会选择(int,bool)构造函数。
有关编译器逻辑的背景知识是什么?
答案 0 :(得分:8)
现在调用构造函数#1的
Aobj2(int, string)
的第二种构造很奇怪。编译器如何使用字符串参数调用(int, bool)
构造函数?
更确切地说,"false"
的类型为const char[6]
,可以decay到const char*
,即一个指针,然后可以implicitly convert到{{1} }。
可以将整数,浮点数,无作用域枚举,指针和指针成员类型的prvalue转换为
bool
类型的prvalue。值零(对于整数,浮点数和无作用域枚举)以及空指针和指向成员的空指针值变为
bool
。所有其他值都变为false
。
对于第四种情况,参数true
与参数std::initializer_list<int>
不匹配,因为没有隐式转换将指针转换为40, "false"
。然后选择采用int
的构造函数,因为如上所述,int, bool
可以隐式转换为"false"
。
答案 1 :(得分:7)
"false"
是一个const char[6]
,它会衰减为const char*
,并且指针可以隐式转换为bool
。这就是为什么编译器可以使用int
和bool
来调用构造函数的原因,因为允许编译器执行 one 隐式转换以使函数参数匹配。