Тип класса для размещения стека. Почему адреса для обоих экземпляров идентификатора одинаковые?

class ID
{
public:
    ID(const std::string& name) :
        name_(name) {}

    // explicit copy constructor as my first solution but gave me same address
    ID(const ID& other)
    { name_ = other.getName(); } 

    std::string getName() const
    { return name_; }

private:
    std::string name_;
};

ID createID(const std::string& name)
{
    ID id(name); // new stack allocation for id
    std::cout << "ID addr: " << &id << "\n";
    return id;
}

int main()
{
    ID my_id = createID("John"); // new stack allocation for my_id
    std::cout << "my_id addr: " << &my_id << "\n";
    std::cout << my_id.getName() << std::endl;
}

Платформа: терминал Ubuntu (подсистема Ubuntu Windows)

Компиляция: g++ file.cpp

Вывод: "Одинаковый адрес между идентификаторами"

Разве на выходе не должен быть другой адрес стека?

Я попытался воспроизвести это с примитивным целым числом (вместо типа класса ID), и он выводит разные адреса для разных экземпляров.

int func(int i)
{
        int j = i;
        std::cout << "i addr: " << &i << std::endl;
        std::cout << "j addr: " << &j << std::endl;
        return i;
}

int main()
{
        int x = 10;

        std::cout << "X addr: " << &x << std::endl;
        int y = func(x);
        std::cout << "Y addr: " << &y << std::endl;
}

1 ответ

Решение

В этой функции:

ID createID(const std::string& name)
{
    ID id(name); // new stack allocation for id
    std::cout << "ID addr: " << &id << "\n";
    return id;
}

для звонка:

ID my_id = createID("John"); // new stack allocation for my_id

похоже, что компилятор выполняет NRVO (названная оптимизация возвращаемого значения). Так что реальной копииid в функции к переменной my_id, а отдельного выделения нет.

Вместо этого эта копия опускается, и вы видите тот же адрес. Итак, комментарий// new stack allocation for my_id на самом деле неверно.

Обратите внимание, что NRVO не гарантируется, поэтому не следует полагаться на такое поведение. Компилятор может сделать копию, что приведет к другим адресам. Фактически это то, что происходит в примере, гдеfunc возвращает int. Поскольку это дешевый для копирования тип, компилятор фактически делает копию, и вы видите разные адреса.

Другие вопросы по тегам