我编写了一个程序来检查类创建的初始化过程,发现多次调用构造函数会更改成员指针地址。看下面的代码片段。
#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。
有人可以解释吗?
答案 0 :(得分:3)
您对FF();
的调用将创建一个新的未命名的基于FF
的对象,构造它(生成您看到的输出),然后立即再次销毁它(对此您不显示任何内容)输出)。这就是ptr
地址似乎变回原来的原因-因为它从未变过。添加一个析构函数,该析构函数打印出this
的地址以查看这种情况。
顺便说一句,在第二个(参数化的)构造函数中使用this->ptr
是未定义行为,因为您从未为ptr
赋值。
如果您打算从参数化构造函数中调用默认构造函数,并且您的编译器支持C ++ 11,则可以delegate使用默认构造函数。
FF(const int* ptrcopy, const int valuecopy): FF() { /* ... */ }
答案 1 :(得分:0)
我认为这是在构造函数2中,您正在打印ptr(0x400b40
)的未初始化值,然后使用FF()
创建FF类型的新对象。然后将为新对象调用构造函数1,它的ptr成员将更改为NULL(因此在打印时它将为0)。新对象的构造函数完成后,它返回到构造函数2(调用了先前对象的析构函数),然后调用init,它将显示ptr的值与以前一样,因为该对象的ptr成员未更改。 / p>
这可能还会帮助您在析构函数中打印内容。那就是FF::~FF()
。
编辑:拼写和析构函数建议
答案 2 :(得分:0)
就像1201ProgramAlarm所说,做FF();
不会 not 调用 current 对象的构造函数。为此,您可以执行以下操作(假设使用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) {
...
}
...
};
答案 3 :(得分:0)
比较以下内容:
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
上调用默认构造函数。当然,只要适当地调用,就可以与 any 构造函数一起使用:
FF() : FF(nullptr, 0) { }
现在,默认构造函数将调用您的第二个构造函数。