奇怪的构造函数行为

时间:2018-11-01 06:09:54

标签: c++ initialization initializer-list

我正在使用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)构造函数。

有关编译器逻辑的背景知识是什么?

2 个答案:

答案 0 :(得分:8)

  

现在调用构造函数#1的Aobj2(int, string)的第二种构造很奇怪。编译器如何使用字符串参数调用(int, bool)构造函数?

更确切地说,"false"的类型为const char[6],可以decayconst 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。这就是为什么编译器可以使用intbool来调用构造函数的原因,因为允许编译器执行 one 隐式转换以使函数参数匹配。