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 类型的纯右值;结果值为假。
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)
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)