c++ - 标准容器封装和基于范围的 for 循环

标签 c++ c++11 containers c++14 encapsulation

我正在设计一个包含两个标准 vector 作为成员的类。我希望能够在 vector 元素上使用基于范围的 for 循环,我想出了这个解决方案

#include <iostream>
#include <vector>

using namespace std;

class MyClass {
public:
  void addValue1(int val){data1_.push_back(val);}
  void addValue2(int val){data2_.push_back(val);}
  vector<int> const & data1() const {return data1_;}
  vector<int> const & data2() const {return data2_;}
  // ...
private:
  vector<int> data1_;
  vector<int> data2_;
  // ...
};

void print1(MyClass const & mc) {
  for (auto val : mc.data1()){
    cout << val << endl;
  }
}

void print2(MyClass const & mc) {
  for (auto val : mc.data2()){
    cout << val << endl;
  }
}

int main(){
  MyClass mc;
  mc.addValue1(1);
  mc.addValue1(2);
  mc.addValue1(3);
  print1(mc);
}

显然,定义 begin()end() 函数的替代方案没有意义,因为我有两个不同的 vector 。

我想请教以下问题:

  • 所提出的解决方案的一个缺点是无法更改两个 vector 的内容(由于 const 限定符)。如果我需要修改 vector 元素,我该如何修改代码? 编辑:修改应保留封装

  • 考虑到数据封装,您认为返回两个 vector 的 (const) 引用是不好的做法吗?

最佳答案

使用像 gsl::span<int> 这样的东西和 gsl::span<const int> .

这是一个最小的:

template<class T>
struct span {
  T* b = 0; T* e = 0;
  T* begin() const { return b; }
  T* end() const { return e; }
  span( T* s, T* f ):b(s),e(f) {}
  span( T* s, std::size_t len ):span(s, s+len) {}
  template<std::size_t N>
  span( T(&arr)[N] ):span(arr, N) {}
  // todo: ctor from containers with .data() and .size()

  // useful helpers:
  std::size_t size() const { return end()-begin(); }
  bool empty() const { return size()==0; }
  T& operator[](std::size_t i) const { return begin()[i]; }
  T& front() const { return *begin(); }
  T& back() const { return *(std::prev(end())); }

  // I like explicit defaults of these:
  span() = default;
  span(span const&) = default;
  span& operator=(span const&) = default;
  ~span() = default;
};

现在你可以写:

span<int const> data1() const {return {data1_.data(), data1_.size()};}
span<int const> data2() const {data2_.data(), data2_.size()};}
span<int> data1() {return {data1_.data(), data1_.size()};}
span<int> data2() {data2_.data(), data2_.size()};}

关于c++ - 标准容器封装和基于范围的 for 循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47519680/

相关文章:

docker - 在Bluemix用户界面中使用命令

c++ - 自定义元素的迭代器在 vector 中

c++ - 关联容器所需的比较器

c++ - 迁移到 Qt5 时无法在子目录中找到头文件

c++ - OpenCV 3.1.0 : Save and load trained SVMs

c++ - 从具有一个分配器的 vector 移动到具有另一个分配器的 vector

c++ - boost::bind 无法绑定(bind)到纯虚基类中定义的非静态函数模板成员类型

c++ - 像列表一样订购但按键访问?

c++ - 通过引用传递 vector 并在基于范围的 for 循环中更改其值?

c++ - Visual C++ 2010 拒绝在调试时显示 std::string 值。显示 <Bad Ptr>