在 C++ 中将 int 作为 bool 参数传递
Passing int as bool argument in C++
有人可以解释这段代码中发生了什么吗:
#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);
class 类型 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 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer
to member type can be converted to a prvalue of type bool. A zero
value, null pointer value, or null member pointer value is converted
to false; any other value is converted to true. For
direct-initialization (8.5), a prvalue of type std::nullptr_t can be
converted to a prvalue of type bool; the resulting value is false.
在此声明中:
toto t = new toto(0);
在表达式 new toto(0)
中,您正在分配具有默认参数 0
的 toto
。此 int
可以隐式转换为 bool
值 false
,并调用 bool
构造函数,结果输出:
constructor bool:false
那么你在做作业:
toto t = /* pointer returned by new */;
此指针可以隐式转换为 bool
,并且由于此指针不是 nullptr
,因此它具有 non-zero 值。这与接受 bool
的 toto
构造函数不是 explicit
的事实相结合意味着 bool
的构造函数被调用用于 t
,导致:
constructor bool:true
这使得 t
的 b
成员具有值 true
,因此下一行代码导致输出:
t.b is true
任何整数值都可以隐式转换为 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() {}
};
有人可以解释这段代码中发生了什么吗:
#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);
class 类型 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 A prvalue of arithmetic, unscoped enumeration, pointer, or pointer to member type can be converted to a prvalue of type bool. A zero value, null pointer value, or null member pointer value is converted to false; any other value is converted to true. For direct-initialization (8.5), a prvalue of type std::nullptr_t can be converted to a prvalue of type bool; the resulting value is false.
在此声明中:
toto t = new toto(0);
在表达式 new toto(0)
中,您正在分配具有默认参数 0
的 toto
。此 int
可以隐式转换为 bool
值 false
,并调用 bool
构造函数,结果输出:
constructor bool:false
那么你在做作业:
toto t = /* pointer returned by new */;
此指针可以隐式转换为 bool
,并且由于此指针不是 nullptr
,因此它具有 non-zero 值。这与接受 bool
的 toto
构造函数不是 explicit
的事实相结合意味着 bool
的构造函数被调用用于 t
,导致:
constructor bool:true
这使得 t
的 b
成员具有值 true
,因此下一行代码导致输出:
t.b is true
任何整数值都可以隐式转换为 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() {}
};