在 C++ 中传递 int 作为布尔参数



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

此处的示例: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;
}

输出:

constructor bool:false
constructor bool:true
t.b is true
constructor bool:false
constructor bool:true
t.b is true

在此声明中

toto t = new toto(0);

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

所以事实上你有

toto t = true;

除了由于分配对象的地址丢失而存在内存泄漏。因此,无法删除分配的对象。

你可以这样想象上面的声明。

toto *ptr = new toto(0)
toto t = ptr;

所以这个输出的第一行

constructor bool:false
constructor bool:true

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

new toto(0)

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

上述声明与本分配语句之间没有太大区别

t = new toto(false);

因为再次在作业的右侧使用了指针。

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

这个作业你可以想象如下

toto *ptr = new toto(false);
t = toto( ptr );

再次出现内存泄漏。

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

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

任何整数值都可以隐式转换为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);

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

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

在此语句中:

toto t = new toto(0);

在表达式new toto(0)中,您将分配一个具有默认参数0toto。此int可以隐式转换为boolfalse,这将调用bool构造函数,从而产生输出:

constructor bool:false

然后你正在做作业:

toto t = /* pointer returned by new */;

这个指针可以隐式转换为bool,并且由于这个指针不是nullptr的,所以它有一个非零值。这与不接受booltoto构造函数不explicit的事实相结合,意味着来自bool的构造函数被调用t,导致:

constructor bool:true

这使得tb成员具有值true,因此下一行代码产生输出:

t.b is true

最新更新