Reputation: 1369
I have this class
class HumanA
{
public:
HumanA(std::string name, Weapon weapon);
~HumanA(void);
inline void attack(void)
{
std::cout << _name << " attacks with his " << _weapon.getType();
}
private:
std::string _name;
Weapon &_weapon;
};
and this constructor
HumanA::HumanA(std::string name, Weapon weapon) : _name(ft::strcapitalize(name)), _weapon(weapon)
{
}
and I get this error at compilation
HumanA.cpp:15:91: error: binding reference member '_weapon' to stack allocated
parameter 'weapon' [-Werror,-Wdangling-field]
...name, Weapon weapon) : _name(ft::strcapitalize(name)), _weapon(weapon)
^~~~~~
./HumanA.hpp:35:12: note: reference member declared here
Weapon &_weapon;
^
1 error generated.
isn't it possible to have a reference to stack allocated memory? This error seems weird to me.
Upvotes: 3
Views: 1287
Reputation: 17454
isn't it possible to have a reference to stack allocated memory? This error seems weird to me.
It certainly is, but you have to make sure the original object lives at least as long as the reference does. Yours… doesn't. It's a by-value constructor parameter that's effectively local to the constructor, so the reference is left dangling pretty much immediately.
Usually you'd only be getting a warning about this, but your compiler is in -Werror
mode, which turns warnings into errors. Good thing too!
If you take a reference into the constructor too, then you'll be binding the reference to the original, original object, which is presumably what you want.
If it's not what you want, if you wanted the class to own a copy of the Weapon
, then just forget the reference and std::move
the constructor argument into the member (or just copy it again if it's cheap to do so).
Upvotes: 0
Reputation: 2861
Think:
Weapon weapon
object?Weapon &_weapon
?The answer to the first question is this: weapon
exists as long as the constructor is executing. This is a stack-allocated variable that ceases to exist the moment the constructor finishes its job.
The answer to the second question is: member _weapon
exists as long as the object that contains this member exists.
So the time of living of weapon
is shorter that that of _weapon
.
Now, what happens when you bind a reference to an object whose time of living is shorter than that of the reference? Well, you'll get a dangling reference. A reference to a memory you don't own. A serious bug that is difficult to spot and difficult to trace unless some special diagnostoc tools have been used, like valgind. In other words, you are free to write this code, but you can access the member only while your program is inside the constructor. This is not something you've intended, isn't it?
Upvotes: 5
Reputation: 118340
isn't it possible to have a reference to stack allocated memory
Of course you can. Except that the problem here is that this "stack allocated memory" disappears when the constructor returns, and attempting to use it from that point results in nasal demons and your compiler is smart enough to detect this bug.
Parameters to all functions, including constructors, get destroyed when the function/constructor returns. Capturing a reference to them does not change that.
If you were to declare a reference in the constructor, to its parameter, and use it only in the constructor, nobody will complain about it.
Upvotes: 0
Reputation: 63775
You are binding a reference to a parameter value. Once the constructor has completed, that parameter is destroyed and the reference is guaranteed to dangle.
Change the parameter to a reference.
HumanA(std::string name, Weapon &weapon);
Upvotes: 0