我编写了一个程序来检查类创建的初始化过程,并发现多次调用构造函数更改了成员指针地址。查看以下片段。
#include <iostream>
using namespace std;
class FF {
public:
FF(){
this->ptr = NULL;
value = 1;
cout << "ptr address in 1: " << this->ptr <<endl;
}
FF(const int* ptrcopy, const int valuecopy){
cout << "ptr address in 2: " << this->ptr << endl;
FF();
/* Is this equivalent with FF() ?
this->ptr = NULL;
value = 1;
*/
init(ptrcopy, valuecopy);
}
void init(const int* ptrcopy, const int valuecopy) {
cout << "ptr address in 3: " << this->ptr << endl;
if (this->ptr != NULL)
{
cout << "error happened, the address of ptr is " << this->ptr << endl;
return;
}
}
private:
int* ptr;
int value;
};
int main(){
int *ptr = new int(10);
int value = 1;
FF fclass(ptr, value);
delete(ptr);
return 0;
}
输出为
ptr address in 2: 0x400b40
ptr address in 1: 0
ptr address in 3: 0x400b40
error happened, the address of ptr is 0x400b40
看来FF()
的调用仅在其空间中将PTR启动到null,而PTR在呼叫后将其更改为原始的0x400B40。
有人可以解释吗?
您对FF();
的调用将创建一个新的,未命名的基于堆栈的FF
对象,构造它(生成您看到的输出),然后立即再次销毁它(对于您不显示任何显示任何内容输出)。这就是为什么ptr
地址似乎会更改的原因 - 因为它从未改变。添加一个打印出this
地址以查看的破坏者。
顺便说一句,您在第二个(参数化)构造函数中使用this->ptr
是未定义的行为,因为您永远不会为ptr
分配值。
如果您的目的是从参数化的构造函数调用默认构造函数,并且编译器支持C 11,则可以委派给默认构造函数。
FF(const int* ptrcopy, const int valuecopy): FF() { /* ... */ }
我认为正在发生的事情是,在构造函数2中,您正在打印PTR(0x400b40
)的非初始化值,然后您正在创建一个使用FF()
的FF类型的新对象。然后,将为新对象调用构造函数1,它的PTR成员将被更改为null(因此,当打印时为0)。在新对象完成的构造函数之后,它返回到构造函数2(调用了先前对象的驱动器2),然后您调用INIT,该INIT将显示与以前相同的PTR值,因为该对象的PTR成员尚未更改。<<<<<<<<<<<<<<<<
它可能会帮助您在灾难中打印物品。那将是FF::~FF()
。
编辑:拼写和驱动器建议
像1201 Programalarm所说的那样,执行FF();
dos not 调用当前对象的构造函数。为此,您将执行以下类似(假设C 11):
class FF {
public:
FF() : ptr(nullptr), value(1) {
cout << "ptr address in 1: " << this->ptr <<endl;
}
FF(const int* ptrcopy, const int valuecopy) : FF() {
cout << "ptr address in 2: " << this->ptr << endl;
init(ptrcopy, valuecopy);
}
void init(const int* ptrcopy, const int valuecopy) {
...
}
...
};
另请参阅此问题。
与以下内容进行比较:
class C
{
public:
C() { std::cout << 'c' }
~C() { std::cout << 'd' }
};
void test()
{
C f;
std::cout << 't';
}
您应该已经知道,在功能末尾创建一个临时对象。您应该看到输出ctd
void test()
{
C();
std::cout << 't';
}
再次相同,有一点差异:执行语句后,对象立即运行范围,因此输出将为cdt
。
现在在构造函数中完全相同,您只需在构造函数内部调用FF()
时创建一个临时的,单独的FF对象。
我想您代替打算构造委员会(自C 11以来可用);但是,语法是不同的:
FF(int const*, int)
: FF() // as if using the initialiser list
{ /* can do some extra work here */ }
现在,在输入功能主体之前,将在this
上调用默认构造函数。当然,只要适当地称为构造函数:
FF() : FF(nullptr, 0) { }
现在,默认构造函数将称您的第二个。