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;
}
Platform: Ubuntu terminal (Windows' Ubuntu Subsystem)
Compilation: g++ file.cpp
Output: "Same address between IDs"
Shouldn't the output provided different stack address?
I tried replicating this with primitive integer (instead of ID class type) and it outputs different address for different instances.
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;
}
In this function:
ID createID(const std::string& name)
{
ID id(name); // new stack allocation for id
std::cout << "ID addr: " << &id << "\n";
return id;
}
for the call:
ID my_id = createID("John"); // new stack allocation for my_id
it appears the compiler is doing NRVO (named return value optimization). So there is no actual copy of id
in the function to the variable my_id
, and no separate allocation.
Instead this copy is elided, and you see the same address. So the comment // new stack allocation for my_id
is actually incorrect.
Note that NRVO is not guaranteed to happen, so you shouldn't rely on this behavior. The compiler could make a copy, resulting in different addresses. In fact this is what happens in the example where func
returns an int
. Since this is a cheap to copy type, the compiler actually makes a copy, and you see different addresses.