简体   繁体   English

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

[英]Multiple calling constructor will change the member pointer address in C++

I write a program to check the init process of class creation, and found calling the constructor multiple times changed the member pointer address. 我编写了一个程序来检查类创建的初始化过程,发现多次调用构造函数会更改成员指针地址。 Look at following snippet. 查看以下代码段。

#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;
}

The output is 输出是

ptr address in 2: 0x400b40
ptr address in 1: 0
ptr address in 3: 0x400b40
error happened, the address of ptr is 0x400b40

It seems the calling of FF() only init the ptr to NULL in its space, and the ptr change back to original 0x400b40 after calling. 似乎FF()的调用仅将ptr在其空间中初始化为NULL,并且在调用后ptr变回到原始的0x400b40。

Can someone explain about it ? 有人可以解释吗?

Your call of FF(); 您对FF();调用FF(); will create a new, unnamed stack based FF object, construct it (generating the output you see), then immediately destroy it again (for which you don't show any output). 将创建一个新的,未命名的基于堆栈的FF对象,对其进行构造(生成您看到的输出),然后立即再次销毁它(对于该对象您不显示任何输出)。 This is why the ptr address seems to change back - because it never changed. 这就是为什么ptr地址似乎会变回来的原因-因为它从未更改。 Add in a destructor that prints out the address of this to see this occur. 添加在打印出的地址的析构函数this看到这种情况发生。

Incidentally, your use of this->ptr in the second (parameterized) constructor is Undefined Behavior because you never assign a value to ptr . 顺便说一句,您在第二个(参数化的)构造函数中使用this->ptr是未定义行为,因为您从未为ptr分配值。

If your intent is to call the default constructor from the parameterized constructor, and your compiler supports C++11, you can delegate to the default constructor. 如果您打算从参数化构造函数中调用默认构造函数,并且您的编译器支持C ++ 11,则可以委托给默认构造函数。

FF(const int* ptrcopy, const int valuecopy): FF() { /* ... */ }

I think what's happening is that in constructor 2 you are printing the uninitialized value for ptr ( 0x400b40 ) and then you are creating a new object of type FF with FF() . 我认为这是在构造函数2中,您正在打印ptr( 0x400b40 )的未初始化值,然后使用FF()创建类型为FF的新对象。 Then constructor 1 will be called for the new object, it's ptr member will be changed to NULL (so when printed it will be 0). 然后将为新对象调用构造函数1,它的ptr成员将更改为NULL(因此在打印时它将为0)。 After the constructor for the new object finishes it returns to constructor 2 (the destructor for the previously object is called) and then you call init which will display the same value for ptr as before since this object's ptr member hasn't been changed. 新对象的构造函数完成后,它将返回到构造函数2(调用了先前对象的析构函数),然后调用init,它将显示ptr的值与以前相同,因为该对象的ptr成员未更改。

It might help you to also print the something in the destructor. 它也可以帮助您在析构函数中打印某些内容。 That would be FF::~FF() . 那将是FF::~FF()

EDIT: Spelling and destructor suggestion 编辑:拼写和析构函数建议

Like 1201ProgramAlarm said, doing FF(); 就像1201ProgramAlarm所说的那样,执行FF(); does not call the constructor of the current object. 调用当前对象的构造函数。 To do so, you would do something like below (assuming C++11): 为此,您可以执行以下操作(假设使用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) {
    ...
  }
  ...
};

See also this question . 另请参阅此问题

Compare to the following: 比较以下内容:

class C
{
public:
    C() { std::cout << 'c' }
    ~C() { std::cout << 'd' }

};

void test()
{
    C f;
    std::cout << 't';
}

You should know about already, you create a temporary object running out of scope at the end of the function. 您应该已经知道了,您在函数末尾创建了一个超出范围的临时对象。 You should see output ctd 您应该看到输出ctd

void test()
{
    C();
    std::cout << 't';
}

Same again, with a little difference: The object runs out of scope right after the statement is executed, so output would be cdt . 再次相同,只是有所不同:执行语句后,对象立即超出作用域,因此输出将为cdt

Now exactly the same happens in your constructor, you just create a temporary, separate FF object when calling FF() inside the constructor's body. 现在,在构造函数中发生完全相同的情况,您只需在构造函数体内调用FF()时创建一个临时的单独FF对象。

I suppose you instead intended constructor delegation (available since C++11); 我想您打算使用构造函数委派(自C ++ 11起可用)。 however, syntax is different: 但是,语法不同:

FF(int const*, int)
    : FF() // as if using the initialiser list
{ /* can do some extra work here */ }

Now, the default constructor will be called on this before entering the function body. 现在,默认的构造函数将在叫this进入函数体之前。 Of course, works with any constructor, as long as called appropriately: 当然,可以与任何构造函数一起使用,只要适当调用即可:

FF() : FF(nullptr, 0) { }

Now, the default constructor would call your second one. 现在,默认构造函数将调用您的第二个构造函数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM