返回班级私有会员"large"好做法是什么?

What is the good practice for returning "large" class private member?

本文关键字:large 是什么 返回      更新时间:2023-10-16
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;
}

我应该避免使用 getData1() 复制它吗?首选常量引用而不是 getData2() 有什么性能优势吗?我应该如何从课堂上返回如此"大"的私人成员?

区别在于用户可以用你的DataType做什么:

  • 使用 getData1 它们只能调用标记为 const 的成员函数,并访问成员变量,就像它们被声明为常量一样,并且只能在返回引用的对象的生存期内。
  • 有了getData2用户可以调用他们想要的任何方法,并根据需要进行修改。

使用getData2的代价是复制:如果DataType有一个昂贵的复制构造函数,则调用可能会变得更加昂贵。

您可以通过实施写入时复制策略并通过引用计数共享数据来改进这一点。当然,用户可以通过在常量引用上调用复制构造函数来手动制作副本:

DataType dtCopy(obj.getData1());

在此示例中,成员data似乎是接口的一部分。目前尚不清楚您是否希望在创建类后数据是可变的。如果没有,您可以简单地将 const 数据成员公开为"数据即接口",如下所示:

typedef std::vector <std::vector <int>> DataType;
class MyClass
{
public:
    MyClass(DataType data_) 
    : data(std::move(data_))
    {
    }
    // data is interface, but it's immutable so perfectly safe
    const DataType data;
};

这在所有情况下都是最佳的,而且它具有自动线程安全的优点。

如果您打算data是可变的,那么正常的做法是提供一个 const 引用访问器和一个可变引用访问器(尽管这实际上在逻辑上等同于简单地在接口上公开数据)

像这样:

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

返回大型类私有成员几乎从来都不是一个好的做法。

你应该使用 getData1() 而不是 getData2()。那里不需要复制。

首选getData1()的原因是因为客户端可以执行const DataType& data = myClass.getData1();,从而避免复制大数据。

这取决于。通常,最好返回对 const 对象的引用,因为您不能 100% 确定客户端是否需要数据副本。即使客户端确实需要数据副本,它们也可以调用复制构造函数。因此,getData1()允许一些选择。有了getData2()你总是必须处理复制构造函数。

const DataType & MyClass::getData1() const
{
    return data;
}

^ 这将返回对常量对象的引用。这是一条路。显然,它不允许对对象进行外部修改。

DataType MyClass::getData2() const
{
    return data;
}

^ 这不适合"酷孩子"。这将在return data上调用您的巨大对象的复制构造函数。

在这种情况下,最好通过 const 引用返回,因为它可以避免不必要的复制。