1

我痴迷于做const真正应该做的事情const,即使这样做似乎有点痛苦。

在这种情况下,我想要一个vector<int>可以添加元素但无法更改其现有元素的元素。问题是这vector<const int>是不允许的。

目的不仅是防止我的类的用户修改他们不应该修改的东西(这可以通过const成员函数中的迭代器轻松完成)。同样重要的是,我自己以后不会在自己的代码中做我不打算做的事情

我找到了两种选择:

  • 改为使用deque<const int>

  • 创建我自己的包装实际的矢量类vector,像这样(我在int这里这样做,但实际上我会使用模板来概括)

    class my_vector {
    private:
      std::vector<int> vec;    
    public:
      std::vector<int>::const_iterator cbegin() { return vec.cbegin(); }
      std::vector<int>::const_iterator cend() { return vec.cend(); }
      void push_back(int i) { vec.push_back(i); }
    };
    

您会推荐以下哪些想法(或其他想法)?编译器会将第二种选择转换为与直接使用向量一样快的代码吗?

4

3 回答 3

1

你的痴迷是可以理解的,我并不反对,但除非你真的迫切需要它,否则所需的努力可能不值得。

假设您vector根据设计要求选择容器作为容器,我不建议将其更改为deque,或任何其他类型。它只会混淆未来的读者(可能是你自己),否则也是一种不好的做法。

如果我们使用您的包装器解决方案,您将不得不隐藏覆盖所有可能修改向量的成员,这是一个问题,因为有许多方法用于访问和修改,例如operator[], at(), front(), back()。这可能会使未来的读者感到困惑,因为他们习惯了“标准”vector行为。

顺便问一下,你确定deque<const int> foo;有效吗?我收到以下错误:

error: invalid conversion from 'const void*' to 'void*'

编辑看来我没有完全回答你的问题。如果你必须选择一个,我会选择包装方法。

于 2012-12-08T13:45:23.393 回答
1

对于这类标准容器几乎完全符合我的需要的情况,我更喜欢私有继承。公共继承通过指向基类的指针导致切片或非虚拟破坏。作文需要太多额外的打字。

私有继承和使用using很好地表达了你的意图。

这是一个例子:

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

class my_vector : private std::vector<int> {
  // Utility type 
  typedef std::vector<int> base;
public:
  // Types I don't need to tweak:
  using base::value_type;
  using base::allocator_type;
  using base::size_type;
  using base::difference_type;
  using base::const_reference;
  using base::const_pointer;
  using base::const_iterator;
  using base::const_reverse_iterator;

  // Types I do need to tweak:
  typedef const_reference reference;
  typedef const_pointer pointer;
  typedef const_iterator iterator;
  typedef const_reverse_iterator reverse_iterator;

  // Constructors
    // Implicit constructors OK
  // Destructors
    // Implicit destructors OK
  // Assignment
    // Implicit assignment OK

  // Methods that I don't need to tweak:
  using base::assign;
  using base::get_allocator;
  using base::empty;
  using base::size;
  using base::max_size;
  using base::reserve;
  using base::capacity;
  using base::clear;
  using base::push_back;
  using base::pop_back;
  using base::swap;

  // Methods I need to tweak
  const_reference at( size_type pos ) const { return base::at(pos); }
  const_reference operator[](size_type pos) const { return base::operator[](pos); }
  const_reference front() const { return base::front(); }
  const_reference back() const { return base::back(); }
  const_iterator begin() const { return base::begin(); }
  const_iterator end() const { return base::end(); }
  const_reverse_iterator rbegin() const { return base::rbegin(); }
  const_reverse_iterator rend() const { return base::rend(); }

  // Methods I need to delete:
    // base::insert;
    // base::erase;
    // base::resize;

};

int main () {
  my_vector m;
  m.push_back(1);
  m.push_back(2);
  m.push_back(3);
  my_vector m2;
  m2 = m;
  std::copy(m2.begin(), m2.end(), std::ostream_iterator<int>(std::cout, "\n"));
}
于 2012-12-08T14:00:21.397 回答
0

标准容器没有什么神奇之处。如果您需要一个具有不同于标准容器特性的容器,请编写您自己的容器。如果其中一个标准容器接近您的需要,请将其用作内部实现。简而言之,my_vector就是要走的路。

于 2012-12-08T13:55:32.190 回答