为什么在类中声明为对象的成员变量的地址值总是变化?在 C++

问题描述

我正在学习 C++ 类。 我正在编写一个名为 User 的类。 成员变量被声明为类中的对象。 返回此对象地址的函数是 getAddr()。 为了您的信息,getAddr() 函数也存在于 User 类中。

打印用户对象的地址值和用户对象中的人物对象时,我发现了一些奇怪的东西。 发现每次调用getAddr()都会改变User对象中Person对象的地址值。

我写的代码如下。

#include <iostream>
#include <sstream>

class Person {
    private:
        int num;
    public:
        Person(){};
        std::string getAddr() {
            std::stringstream ss;
            ss << this;
            return (ss.str());
        }
};

class User {
    private:
        Person _person;
        Person *_ptr_person;
    public:
        User() {
            this->_ptr_person = new Person();
            this->_person = Person();
        }
        std::string getAddr() {
            std::stringstream ss;

            ss << this;
            return (ss.str());
        }
        Person *getPtrPerson() {
            return this->_ptr_person;
        }
        Person getPerson() {
            return this->_person;
        }
        ~User() {
            delete this->_ptr_person;
        }
};

void run()
{
    User a = User();

    // User address
    std::cout << a.getAddr() << std::endl;
    std::cout << a.getAddr() << std::endl;
    std::cout << a.getAddr() << std::endl;
    // doesn't changed
    std::cout << std::endl;
    
    // Person's address in User
    std::cout << a.getPerson().getAddr() << std::endl;
    std::cout << a.getPerson().getAddr() << std::endl;
    std::cout << a.getPerson().getAddr() << std::endl;
    // changed
    std::cout << std::endl;

    // Ptr Person's address in User
    std::cout << a.getPtrPerson()->getAddr() << std::endl;
    std::cout << a.getPtrPerson()->getAddr() << std::endl;
    std::cout << a.getPtrPerson()->getAddr() << std::endl;
    // doesn't changed
    std::cout << std::endl;

}

int main(void)
{
    run();
}

这段代码输出如下:

enter image description here

如果查看中间三行的输出,可以看到地址值一直在变化。

但是,如果将 Person 对象声明为 User 对象内的指针并通过动态赋值生成它,则地址值保持不变(以下三行的输出)。

为什么会这样?

问题如下:

  • 为什么声明为对象的成员变量的地址总是改变
  • 如果声明为对象的成员变量是Pointer,则地址值保持不变(我觉得很自然)

解决方法

地址发生变化,因为当您调用 a.getPerson() 时,从函数返回的人是原始用户的副本,该人是 User 的类成员。