Тип класса для размещения стека. Почему адреса для обоих экземпляров идентификатора одинаковые?
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
. Поскольку это дешевый для копирования тип, компилятор фактически делает копию, и вы видите разные адреса.