有人可以解释一下这段代码中发生了什么:
此处的示例: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)
中,您将分配一个具有默认参数0
的toto
。此int
可以隐式转换为bool
值false
,这将调用bool
构造函数,从而产生输出:
constructor bool:false
然后你正在做作业:
toto t = /* pointer returned by new */;
这个指针可以隐式转换为bool
,并且由于这个指针不是nullptr
的,所以它有一个非零值。这与不接受bool
toto
构造函数不explicit
的事实相结合,意味着来自bool
的构造函数被调用t
,导致:
constructor bool:true
这使得t
的b
成员具有值true
,因此下一行代码产生输出:
t.b is true