> DataType; class MyClass...">

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?

+3


source to share


7 replies


The difference is what users can do with your DataType

:

  • c getData1

    they can only call marked member functions const

    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());

      

+4


source


Returning a private class to a large class is almost never good practice.



+2


source


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;
};

      

+1


source


Returning by constant reference is preferred in this case, as it avoids unnecessary copying.

0


source


You should be using getData1 () and not getData2 (). Copying is not required there.

0


source


The reason for preference getData1()

is what the client can do const DataType& data = myClass.getData1();

to avoid copying big data.

0


source


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

.

0


source







All Articles