MkjG
MkjG

Reputation: 144

Default move constructor of classes with reference members

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

Answers (2)

Jarod42
Jarod42

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

eerorika
eerorika

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

Related Questions