在C++、什么选择我有暴露出一个集合,从观点的性能和数据的完整性?

我的问题是,我希望返回的内部清单数据的来电,但是我不想生成的副本。丹让我带回一个参考清单,或者一个指的清单。但是,我不是疯狂让这叫改变的数据,我只是想让他读取数据。

  • 我必须要选择之间的性能和数据的完整性?
  • 如果是这样,是在一般更好地去的一种方式或是就特定的情况?
  • 是否还有其他的选择吗?
有帮助吗?

解决方案

RichQ的答案 是一个合理的技术,如果你使用一个数组,矢量,等等。

如果你使用一个收集这并不是编制索引序数值...或者你认为 可能会需要 在某一点在最近的将来...然后您可能想要考虑暴露你自己的迭代的类型(s)和相关的 begin()/end() 方法:

class Blah
{
public:
   typedef std::vector<mydata> mydata_collection;
   typedef myDataCollection::const_iterator mydata_const_iterator;

   // ...

   mydata_const_iterator data_begin() const 
      { return myPreciousData.begin(); }
   mydata_const_iterator data_end() const 
      { return myPreciousData.end(); }

private:
   mydata_collection  myPreciousData;
};

...然后你就可以使用在正常的方式:

Blah blah;
for (Blah::mydata_const_iterator itr = blah.data_begin();
   itr != blah.data_end();
   ++itr)
{
   // ...
}

其他提示

多次呼叫者想访问只是以循环的集合。采取一页的红宝石的书和使迭代的私人方面类。

#include <algorithm>
#include <boost/function.hpp>

class Blah
{
  public:
     void for_each_data(const std::function<void(const mydata&)>& f) const
     {
         std::for_each(myPreciousData.begin(), myPreciousData.end(), f);
     }

  private:
     typedef std::vector<mydata> mydata_collection;
     mydata_collection  myPreciousData;
};

用这种方法,你正在没有暴露出任何关于你的内,即你甚至 一个收集。

也许这样的事情?

const std::vector<mydata>& getData()
{
  return _myPrivateData;
}

这里的好处是,它是非常非常简单,并作为安全的,因为你盖廷C++。你可以抛弃这样RobQ建议,但没有什么你可以这样做,将防止有人从那如果你不是复制。在这里,你会有用 const_cast, ,这是很容易察觉,如果你正在寻找它。

迭代,或者,可能获得你差不多同样的事情,但这是更为复杂。只有加入的利益使用的迭代在这里(我能想到的)就是你可以有更好的封装。

使用的常量引用或共用的指针,将只会帮助,如果内容的基础集合不随时间而改变。

考虑你的设计。不会的呼叫者的真正需要看的内部阵?你能重组的代码这样的呼叫者告诉对象做什么用的阵?E.g., 如果叫打算搜索阵列,可能在所有人象这样做?

你可以通过一个参考的结果向量功能。在一些编译器,可能导致略微更快的代码。

我会建议试图重新设计首先,将有一个干净的解决方案第二,优化业绩的第三(如果必要)。

一个优势的两@Shog9和@RichQ的解决方案是,他们去几个客户从收集执行情况。

如果你决定第改变您的收藏类别的东西,你的客户仍将工作。

你想要什么是只读的访问没有复制整个blob的数据。你有几个选项。

首先,你能回const refererence为什么你的数据的容器,像上述建议:

const std::vector<T>& getData() { return mData; }

这个有缺点的具体性:你不能改变你的存储数据的内部不断变化的界面类。

其次,你可以回const-ed指针的实际数据:

const T* getDataAt(size_t index)
{
   return &mData[index];
}

这是一位好,但也需要您提供一个getNumItems呼叫,并防止越界指数。此外,常量性的,你指的是轻易抛弃,和你的数据是现在读写。

另一个选择是提供一个对迭代,这是一个比较复杂。这个具有相同的优点的指针,以及不(必然)需要提供一个getNumItems话,并有相当多的工作涉及到条的迭代他们的const性。

可能是最简单的方法来管理,这是通过使用一种提升,范围:

typedef vector<T>::const_iterator range_iterator_type;
boost::iterator_range< range_iterator_type >& getDataRange()
{
    return boost::iterator_range(mData.begin(), mData.end());
}

这个具有优势的范围内正在组合筛选,等等,你可以看到的 网站.

使用const是一个合理的选择。你也可能想退房的提高C++图书馆,为它们的共同指针的执行。它提供了优势,即指针你可能有要求返回一个共用针对"null"一个参考不会允许。

http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/smart_ptr.htm

在你的情况下,您会使共享指的类型的常量,以禁止。

如果你有一个 std::list 普通老数据(是什么。净会打电话的价值类型'),然后返回const参照该名单将被罚款(无视邪恶的东西喜欢 const_cast)

如果你有一个 std::list 指针(或 boost::shared_ptr's)然后,将只会阻止你修改的集合,而不是项目 集合。我的C++是太锈能够告诉你答案就在这一点:-(

我建议使用回调线沿线的 EnumChildWindows.你必须找到一些手段,以防止用户更改你的数据。也许用一个 const 指针/参考。

另一方面,可以通过一个复制的每个元素的回呼功能复盖复制。(你不想生成的副本,你的整个集合。我只是建议制作一份一种元素在一段时间。那应该不需要太多的时间/存储器)。

MyClass tmp;
for(int i = 0; i < n; i++){
    tmp = elements[i];
    callback(tmp);
}

以下两个条款阐述的一些问题的参与,以及需要,包封的容器类。虽然它们不提供一个完整的工作方案,它们基本上会导致同样的方法作为给出通过Shog9.

第1部分: 封装和吸血鬼
第2部分(免费登记,现在是需要读这个): 火车事故发现
通过微信、海

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top