Reputation: 144
This is a minimal example, extracted from a larger project.
#include <vector>
#include <cassert>
using namespace std;
class Data
{
int value_;
public:
int const& value = value_;
Data(int init)
{
value_ = init;
assert(value == value_);
}
//Data(Data const& other)
//{
// value_ = other.value_;
//}
// Data(Data && other) = default;
~Data()
{
assert(value == value_);
}
};
int main()
{
std::vector<Data> datas;
for (int i = 0; i < 10; ++i)
{
datas.push_back(Data(i));
}
}
Assertion in destructor fails at some point; at which point I can't tell. I am dumbfounded. Providing copy c-tor works, but then enabling default move-ctor fails again.
How does default move/copy c-tor handles such references? I can't analyze with debugger what is happening behind the scenes.
Is using public const& a valid way in C++ to provide a getter?
Upvotes: 3
Views: 505
Reputation: 218138
Default copy-constructor
Data(Data const&) = default;
is mostly equivalent to:
Data(Data const& rhs) :
value_(rhs.value_), // Copy value
value(rhs.value) // alias the same value as rhs.value, so probably rhs.value_
{
}
So you don't point on internal member as you expect.
Same for default move constructor with some std::move
.
Upvotes: 3
Reputation: 238441
How does default move/copy c-tor handles such references?
The member of the copy will refer to the same object which the member of the source refers to.
In this case the referred object is another member. So, if you copy B
from A
, then the reference member of B
will refer to the object member of A
, because that is what the reference member of A
referred to. if A
is destroyed, that reference member of B
will be left danging and accessing the object (which no longer exists) through it has undefined behaviour.
Indeed, you can use a custom copy / move constructors in order to initialise the reference to refer to some other object, but reference to a member is in general quite useless.
Is using public const& a valid way in C++ to provide a getter?
It is not a good solution.
Upvotes: 3