用const std :: vector包装现有内存? [英] Wrap existing memory with 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屋!