使用const std :: vector包装现有内存?

Rub*_*Rad 13 c++ stl const vector

好的,所以我最近了解到(a)std :: vector按定义/标准使用连续内存,因此(b)&(v [0])是连续内存块的地址,你可以读/写作为一个老式的C-array.喜欢...

void printem(size_t n, int* iary)
{ for (size_t i=0; i<n; ++i) std::cout << iary[i] << std::endl; }
void doublem(size_t n, int* iary)
{ for (size_t i=0; i<n; ++i) iary[i] *= 2; }

std::vector<int> v;
for (size_t i=0; i<100; ++i) v.push_back(i);
int* iptr = &(v[0]);
doublem(v.size(), iptr);
printem(v.size(), iptr);
Run Code Online (Sandbox Code Playgroud)

好的,这很酷,但我想走向另一个方向.我有很多很多现有的代码

double computeSomething(const std::vector<SomeClass>& v) { ... }
Run Code Online (Sandbox Code Playgroud)

如果我有一个C-array对象,我可以使用这样的代码:

SomeClass cary[100]; // 100*sizeof(SomeClass)
// populate this however
std::vector<SomeClass> v;
for (size_t i=0; i<100; ++i) v.push_back(cary[i]);
// now v is also using 100*sizeof(SomeClass)
double x = computeSomething(v);
Run Code Online (Sandbox Code Playgroud)

我想这样做(a)没有额外的空间和(b)没有额外的时间将所有数据的冗余副本插入到向量中.请注意,"只是改变你的愚蠢计算,蠢货"是不够的,因为有成千上万的这样的功能/方法表现出这种模式并不在我的控制之下,即使它们太多而无法改变所有这些.

还要注意,因为我只对const std :: vector&usage感兴趣,所以不用担心我的原始内存需要调整大小,甚至修改.我想要一个类似const std :: vector构造函数的东西,但我不知道该语言是否允许特殊构造函数用于类的const实例,如:

namespace std { template <typename T> class vector {
  vector() { ... }
  vector(size_t n) { ... }
  vector(size_t n, const T& t) { ... }
  const vector(size_t n, T*) { ... } // can this be done?
...
Run Code Online (Sandbox Code Playgroud)

如果这是不可能的,那么从std :: vector派生的一个容器如何调用std :: const_vector,它(a)可以从一个指向c-array和一个大小的指针构造,并且(b)有目的地没有实现non -const方法(push_back,resize等),所以即使typename为const_vector的对象实际上不是const对象,只提供const方法的接口实际上是const(并且任何错误的修改尝试都是在编译时捕获)?

更新:有点乱搞表明这"解决"我的问题与Windows实现std :: vector:

template <typename T>
class vector_tweaker : public std::vector<T> {
public:
  vector_tweaker(size_t n, T* t) {
    _saveMyfirst = _Myfirst;
    _saveMylast  = _Mylast;
    _saveMyend   = _Myend;
    _Myfirst = t;
    _Mylast  = t + n;
    _Myend   = t + n;
  }
  ~vector_tweaker() {
    _Myfirst = _saveMyfirst;
    _Mylast  = _saveMylast;
    _Myend   = _saveMyend; // and proceed to std::vector destructor
  }
private:
  T* _saveMyfirst;
  T* _saveMylast;
  T* _saveMyend;
};
Run Code Online (Sandbox Code Playgroud)

但当然"解决方案"是可怕的,因为(a)它没有提供保护来防止通过执行resize()或push_back()来删除原始内存的基类(除了只构造const vector_tweaker()的细心用户) - - 和(b)它特定于std :: vector的特定实现,并且必须为其他实现重新实现 - 如果其他平台确实只将其std :: vector成员数据声明为protected:就像microsoft所做的那样(似乎是馊主意).

Ale*_*nko 2

您可以尝试使用 C++11 中引入的引用逻辑存储std::reference_wrapper<>

SomeClass cary[100];
// ...
std::vector<std::reference_wrapper<SomeClass>> cv;
cv.push_back(cary[i]);   // no object copying is done, reference wrapper is stored
Run Code Online (Sandbox Code Playgroud)

或者,如果没有 C11,您可以为字节创建此类模板类的特化 - char。char*然后,对于C 数组的构造函数,您可以使用::memcpy: ,不幸的是,它会使用两倍的内存。

::memcpy(&v[0], c_arr, n);
Run Code Online (Sandbox Code Playgroud)

像这样的东西:

template <typename T> class MyVector : public std::vector<T> {
};

template <> class MyVector<char> : public std::vector<char> {
    public:
    MyVector<char>(char* carr, size_t n) : std::vector<char>(n) {
        ::memcpy(&operator[](0), carr, n);
    }
};
Run Code Online (Sandbox Code Playgroud)

我的建议是——尽可能将所有 C 数组替换为向量,这样就不需要额外的复制了。

  • 专门化 `std::vector&lt;char&gt;` 将是未定义的行为。命名空间 std 中的专业化需要以某种方式涉及用户定义的类型,而 char 则不需要。 (2认同)