奇怪的构造函数行为

mad*_*adu 4 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;
}
Run Code Online (Sandbox Code Playgroud)

输出是:

Constructor #1
Constructor #1
Constructor #2
Constructor #1
Run Code Online (Sandbox Code Playgroud)
  • 对构造函数#1的第一次调用很好

  • 现在Aobj2(int, string)调用构造函数#1 的第二个构造很奇怪.编译器如何(int, bool)使用字符串参数调用构造函数?"false" bool甚至没有转换为int.

  • Aobj3也行.虽然initializer_list类型为int,但编译器会因为大括号初始化而调用它,并将bool转换为int.

  • 这一次再次让我感到困惑.我原以为这是一个错误,因为字符串不能转换为int(就像bool一样),并且还期望编译器调用initializer_list构造函数,因为它是一个支撑初始化.但编译器选择(int,bool)构造函数.

什么是编译器逻辑的背景?

son*_*yao 8

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

更确切地说,"false"是一个类型的const char[6],可能衰减const char*,即一个指针,然后可以隐式转换bool.

可以将整数,浮点,无范围枚举,指针和指向成员类型的prvalue转换为类型的prvalue bool.

值零(对于整数,浮点和未对齐枚举)以及空指针和空指针到成员值变为false.所有其他价值观成为true.

对于第四种情况,参数std::initializer_list<int>不能与参数匹配40, "false",因为没有隐式转换将指针转换为int.然后选择构造函数int, bool,因为"false"可以bool如上所述隐式转换.

  • @CIsForCookies我得到了你的意思,但这并不容易解释.将指针转换为`bool`对我来说似乎很简单,行为简单明了; 转换后的结果取决于指针是否为空指针,然后它可用于表示指针是否为空指针.对于`bool`,转换为`int`并不明显; 在概念中,指针只是一个指向某个对象的对象,那么将它转换为"int"的目的是什么?我们不能将转换后的结果用于算术运算.它可能是内存地址,但它不是int的一般用例. (3认同)

Jes*_*uhl 7

"false"是一个const char[6]衰变const char*和指针可以隐式转换为bool.这就是为什么编译器可以使用a int和a 来调用构造函数bool,因为允许编译器执行一次隐式转换以使函数参数匹配.

  • @Scheff有趣的案例.将`const char*`转换为`std :: string`需要用户定义的转换(通过`std :: string`的构造函数); 将`const char*`转换为`bool`是标准转换.然后是后者. (2认同)