What is a good practice for the return of a private member of a "large" class?
typedef std::vector <std::vector <int>> DataType;
class MyClass
{
public:
const DataType &getData() const;
DataType getData2() const;
private:
DataType data;
};
const DataType &MyClass::getData1() const
{
return data;
}
DataType MyClass::getData2() const
{
return data;
}
Shouldn't you copy it using getData1 ()? Is there any performance advantage to prefer a const reference over getData2 ()? How do I get such a "big" private member back from the class?
source to share
The difference is what users can do with your DataType
:
- c
getData1
they can only call marked member functionsconst
and access the member variables as if they were declared constant, and only for the entire life cycle of the object that was returning a reference. - c,
getData2
users can call whatever methods they want and make the necessary changes.
The cost of use is getData2
copied: if it DataType
has an expensive copy constructor, the calls can become significantly more expensive.
You can improve this by implementing a copy-on-write and reference-counted communication strategy. Of course, users will be able to make copies manually by calling the permalink copy constructor:
DataType dtCopy(obj.getData1());
source to share
In this example, it appears that the element is data
actually part of the interface. It is not clear if you are going to change the data after creating the class. If not, you can simply expose the const data member as "data as interface" like this:
typedef std::vector <std::vector <int>> DataType;
class MyClass
{
public:
MyClass(DataType data_)
: data(std::move(data_))
{
}
// data is interface, but it immutable so perfectly safe
const DataType data;
};
which will be optimally efficient in all cases, plus it has the advantage of being automatically thread safe.
If you assume what data
is mutable, then it is common to provide a const-backed helper plus a mutable reference accessor (although this is actually logically equivalent to simply displaying data on an interface)
something like that:
class MyClass
{
public:
MyClass(DataType data)
: _data(std::move(data))
{
}
// immutable access
const DataType& data() const { return _data; }
// mutable access
DataType& data() { return _data; }
// another option - allow the client to move the data out of me
DataType&& steal_data() {
return std::move(_data);
}
private:
DataType _data;
};
source to share
It depends. It is generally best to return a reference to a const object, you are not 100% sure that your client will need a copy of the data. Even if your client needs a copy of the data, they can call the copy constructor on their side. Thus, getData1()
allows you to use some parameters. Since getData2()
you always have to deal with the copy constructor.
const DataType & MyClass::getData1() const
{
return data;
}
^ This will return a persistent object reference. This is the way. Obviously, this will not allow external modification of the object.
DataType MyClass::getData2() const
{
return data;
}
^ And this is not for "cool kids". This will call your huge object copy constructor on return data
.
source to share