一个元素不能改变的非守恒向量

A nonconst vector whose elements cannot change - alternatives

本文关键字:向量 能改变 不能 一个 元素      更新时间:2023-10-16

我痴迷于制作真正应该是constconst,即使这样做看起来有点痛苦。

在这种情况下,我想要一个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); }
    };
    

您会推荐以下哪种想法(或其他想法)?编译器会把第二个替代方案变成和直接使用向量一样快的代码吗?

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

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

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

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

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

编辑我似乎没有完全回答你的问题。如果选择一个,我会选择包装器方法。

我更喜欢私有继承,因为这类标准容器几乎完全符合我的需求。公共继承通过指向基类的指针导致切片或非虚拟销毁。作文需要额外打字。

私人继承和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"));
}

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