多个调用构造函数将更改C 中的成员指针地址



我编写了一个程序来检查类创建的初始化过程,并发现多次调用构造函数更改了成员指针地址。查看以下片段。

#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) { }

现在,默认构造函数将称您的第二个。

相关内容

  • 没有找到相关文章

最新更新