在 C++ 中将 int 作为 bool 参数传递

Ser*_*rge 43 c++ constructor pointers boolean implicit-conversion

有人可以解释一下这段代码中发生了什么:

这里的例子: https : //ideone.com/1cFb4N

#include <iostream>

using namespace std;

class toto
{
public:
    bool b;
    toto(bool x)
    {
        cout<< "constructor bool:" << (x ? "true": "false")<<endl;
        b = x;
    }
    ~toto() {}
};

int main()
{
    toto t = new toto(0);
    cout << "t.b is " << (t.b ? "true": "false")<<endl;
    t = new toto(false);
    cout << "t.b is " << (t.b ? "true": "false")<<endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

输出:

constructor bool:false
constructor bool:true
t.b is true
constructor bool:false
constructor bool:true
t.b is true
Run Code Online (Sandbox Code Playgroud)

Vla*_*cow 77

在本声明中

toto t = new toto(0);
Run Code Online (Sandbox Code Playgroud)

t类类型的对象toto由表达式返回的指针初始化new toto(0)。由于返回的指针不等于nullptr然后它被隐式转换为布尔值 true。

所以实际上你有

toto t = true;
Run Code Online (Sandbox Code Playgroud)

除了由于分配对象的地址丢失而导致内存泄漏。所以分配的对象不能被删除。

您可以通过以下方式想象上面的声明。

toto *ptr = new toto(0)
toto t = ptr;
Run Code Online (Sandbox Code Playgroud)

所以这个输出的第一行

constructor bool:false
constructor bool:true
Run Code Online (Sandbox Code Playgroud)

对应于参数为 0 的动态创建的对象

new toto(0)
Run Code Online (Sandbox Code Playgroud)

然后返回的指针用作初始化器,并隐式转换true为用于初始化声明对象的布尔值t。因此,第二行显示了值为 true 的转换构造函数(带参数的构造函数)的调用。

上面的声明和这个赋值语句没有太大区别

t = new toto(false);
Run Code Online (Sandbox Code Playgroud)

因为在赋值的右手边再次使用了一个指针。

因此,隐式定义的复制赋值运算符将指针的值转换为不等于nullptr布尔值true

这个作业你可以想象如下方式

toto *ptr = new toto(false);
t = toto( ptr );
Run Code Online (Sandbox Code Playgroud)

再次出现内存泄漏。

来自 C++ 14 标准(4.12 布尔转换)

1 算术、无作用域枚举、指针或指向成员类型的指针的纯右值可以转换为 bool 类型的纯右值。零值、空指针值或空成员指针值转换为 false;任何其他值都将转换为 true。对于直接初始化 (8.5), std::nullptr_t 类型的纯右值可以转换为 bool 类型的纯右值;结果值为假。

  • 顺便说一句,这就是为什么采用单个参数的构造函数应该_始终_被标记为“显式”。 (25认同)

Ala*_*les 20

任何整数值都可以隐式转换为bool,0 转换为false,所有其他值转换为true

这同样适用于指针,空指针转换为false,所有其他指针转换为true

toto t = new toto(0); 相当于:

// Create new toto instance, convert 0 to false and assign to p
toto* p = new toto(0);
// Create toto instance on the stack and convert non-null pointer p to true
toto t = toto(p);
Run Code Online (Sandbox Code Playgroud)

您可以通过将单参数构造函数标记为 来防止这些令人惊讶的转换explicit,这意味着在隐式转换期间不允许考虑它们:

class toto
{
public:
    bool b;
    explicit toto(bool x)
    {
        cout<< "constructor bool:" << (x ? "true": "false")<<endl;
        b = x;
    }
    ~toto() {}
};
Run Code Online (Sandbox Code Playgroud)

  • **我几乎总是在我的 C++ 类中将单参数构造函数标记为“显式”(有点像经验法则)**。一些 IDE 将为新类提供一个模板,其构造函数标记为“explicit”(例如:“qtcreator”创建继承自“QWidget”的新类)。 (4认同)
  • @Peter-ReinstateMonica 是的,`toto t = toto(false);` 相当于 `toto t(false);`,`toto t = false;` 通过隐式转换 (2认同)

cig*_*ien 19

在此声明中:

toto t = new toto(0);
Run Code Online (Sandbox Code Playgroud)

在表达式中,new toto(0)toto使用默认参数分配 a 0。这int可以隐式转换为boolvalue false,并且 this 调用bool构造函数,从而产生输出:

constructor bool:false
Run Code Online (Sandbox Code Playgroud)

然后你在做任务:

toto t = /* pointer returned by new */;
Run Code Online (Sandbox Code Playgroud)

此指针可以隐式转换为bool,并且由于此指针不是nullptr,因此它具有非零值。这与toto接受 a的构造函数bool并不explicit意味着bool调用 for的构造函数的事实相结合t,导致:

constructor bool:true
Run Code Online (Sandbox Code Playgroud)

这使得b成员t具有值true,因此下一行代码导致输出:

t.b is true
Run Code Online (Sandbox Code Playgroud)