用const std :: vector包装现有内存? [英] Wrap existing memory with const std::vector?

查看:114
本文介绍了用const std :: vector包装现有内存?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,因此我最近了解到(a)std :: vector按照定义/标准使用连续内存,因此(b)&(v [0])是该连续内存块的地址,您可以可以读/写为老式的C数组。像...

OK, so I recently learned that (a) std::vector uses contiguous memory by definition/standard, and thus (b) &(v[0]) is the address of that contiguous block of memory, which you can read/write to as an old-skool C-array. Like...

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);

好的,这很酷,但我想朝另一个方向发展。我有很多现有代码,例如

OK, so that's cool, but I want to go in the other direction. I have lots and lots of existing code like

double computeSomething(const std::vector<SomeClass>& v) { ... }

如果我有对象的C数组,则可以使用如下代码:

If I have a C-array of objects, I can use such code like this:

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);

我想这样做(a)没有额外的空间,(b)没有额外的时间将所有这些数据的冗余副本插入向量的过程。请注意,仅仅改变愚蠢的computeSomething,白痴是不够的,因为成千上万的此类函数/方法都表现出这种模式,这些模式/方法不在我的控制范围内,即使它们太多了,也无法更改它们。

I would like to do that (a) without the extra space and (b) without the extra time of inserting a redundant copy of all that data into the vector. Note that "just change your stupid computeSomething, idiot" is not sufficient, because there are thousands of such functions/methods that exhibit this pattern that are not under my control and, even if they were are too many to go and change all of them.

还要注意,因为我只对const std :: vector&不用担心,我的原始内存将永远需要调整大小,甚至可以修改。我想要类似const std :: vector的构造函数,但是我不知道该语言是否允许类的const实例使用特殊的构造函数,例如:

Note also that because I am only interested in const std::vector& usage, there is no worry that my original memory will ever need to be resized, or even modified. I would want something like a const std::vector constructor, but I don't know if the language even allows special constructors for const instances of a class, like:

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?
...

如果这不可能,那么从std派生的容器怎么样:: vector称为std :: const_vector,它(a)可以从指向c数组和大小的指针构造,并且(b)有目的地没有实现非const方法(push_back,resize等),因此即使类型名称为const_vector的对象实际上不是const对象,仅提供const方法的接口实际上也会使其成为const(并且任何错误的修改尝试都会在编译时捕获)?

If that is not possible, how about a container derived off of std::vector called std::const_vector, which (a) could construct from a pointer to a c-array and a size, and (b) purposefully did not implement non-const methods (push_back, resize, etc.), so then even if the object with a typename of const_vector is not actually a const object, the interface which only offers const methods makes it practically const (and any erroneous attempts to modify would be caught at compile time)?

更新:有点混乱,表明这可以解决我在Windows上实现std :: vector的问题:

UPDATE: A little messing around shows that this "solves" my problem wrt Windows-implementation of 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;
};

但是,当然,解决方案是可怕的,因为(a)它没有针对基类的保护通过执行resize()或push_back()删除原始内存(小心的用户只构造const vector_tweaker()除外),并且(b)它特定于std :: vector的特定实现,并且具有要为其他人重新实现-如果确实其他平台仅声明其std :: vector成员数据受保护:就像Microsoft所做的那样(似乎是个坏主意)。

But of course that "solution" is hideous because (a) it offers no protection against the base class deleting the original memory by doing a resize() or push_back() (except for a careful user that only constructs const vector_tweaker()) -- and (b) it is specific to a particular implementation of std::vector, and would have to be reimplemented for others -- if indeed other platforms only declare their std::vector member data as protected: as microsoft did (seems a Bad Idea).

推荐答案

您可以尝试使用 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

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

Or without C11, you can create a specialization of such template class for bytes - char. Then for the constructor from char* C-array you can use ::memcpy: which unfortunately will then use twice as much memory.

::memcpy(&v[0], c_arr, n);

类似这样的东西:

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);
    }
};

我的建议-如有可能,将所有C数组替换为向量,这样就不会产生额外的复制需要。

What I would recommend - replace all C-arrays to vectors where possible, then no extra copying will be needed.

这篇关于用const std :: vector包装现有内存?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆