[英]Pointer arithmetic with std::vector
Previously, I was working with some code in a library that had the interface 以前,我正在使用具有接口的库中的一些代码
void f( T* x );
void g( T* x );
where 哪里
f
would fill the first m
entries of x
with some values (overwriting whatever is in x
) f
将用一些值填充x
的前m
个条目(覆盖x
任何值) g
would fill the first n
entries of x
with some values (overwriting whatever is in x
) g
将用一些值填充x
的前n
个条目(覆盖x
任何值) I wanted to concatenate these two values, so I did this 我想将这两个值连接起来,所以我这样做了
void concat( T* x ){
f(x);
x += m;
g(x);
x += n;
...
}
Actually, there were about 10 such functions that I concatenated using pointer arithmetic like this. 实际上,大约有10个这样的函数是我使用指针运算法则进行连接的。
Now we are trying to use a different library for the same purpose. 现在,我们正试图将不同的库用于相同的目的。 However, the new library has the interface
但是,新库具有接口
void f_new( std::vector<T> & x );
void g_new( std::vector<T> & x );
where again, these functions fill the first m
and n
elements of x
, respectively, (overwriting whatever is currently in x
). 同样,这些函数分别填充
x
的前m
和n
元素(覆盖x
当前存在的任何内容)。 Furthermore, I must create a new concat
function with the signature 此外,我必须使用签名创建一个新的
concat
函数
void concat_new( std::vector<T> & x ){
// TODO
...
}
What is the most efficient way of achieving the previous result with vectors? 用向量获得先前结果的最有效方法是什么? The only way I can figure out how to do this is by copying data between calls.
我能弄清楚如何做到这一点的唯一方法是在调用之间复制数据。
NOTE: I can't modify the signatures for concat_new, f_new, or g_new 注意:我不能修改concat_new,f_new或g_new的签名
There is no efficient way of doing this. 没有有效的方法来执行此操作。
A good library should use iterators. 一个好的库应该使用迭代器。 If it does not you will have to copy the elements.
如果不是,则必须复制元素。
However: You can optimize a bit by reserving space for the target vector if you know the final size. 但是:如果知道最终大小,可以通过为目标向量保留空间来优化一点。
void concat( std::vector<T>& x ){
x.reserve(m+n+...);
f(x);
std::vector<T> buffer;
buffer.reserve(std::max({n, ...}));
g(buffer);
x.insert(x.end(), buffer.begin(), buffer.end());
...
}
by reusing buffer
you can at least skip the reallocations. 通过重用
buffer
您至少可以跳过重新分配。
IF you could change the signature of f then change it to 如果可以更改f的签名,然后将其更改为
void f(std::vector<T>::iterator begin, std::vector<T>::iterator end) {
... // (should use 'end' at least to check the target size)
}
You can always use a wrapper for backward compatibility: 您始终可以使用包装器来实现向后兼容性:
void f(std::vector<T>& x)
{
f(x.begin(), x.end());
}
Then use 然后使用
void concat( std::vector<T>& x) {
assert(x.size() >= m+n);
f(x.begin(), x.begin() + m);
g(x.begin() + m, x.begin() + m + n);
}
But make sure x is large enough! 但是请确保x足够大!
Carry on using the old f
and g
, they are more applicable to you than f_new
and g_new
. 继续使用旧的
f
和g
,它们比f_new
和g_new
更适合您。
void concat_new( std::vector<T> & x )
{
auto it = x.data();
f(it);
it += m;
g(it);
it += n;
...
}
Petition the author of the library to adopt @bartop's signatures (as an overload, perhaps) 请图书馆的作者采用@bartop的签名 (也许是重载)
I think that instead of passing whole std::vectors, the vector's iterator would be sufficient for Your task. 我认为,与传递整个std :: vectors相比,vector的迭代器足以完成您的任务。 It gives You exactly the same functionallity as the pointer and works with vector.
它为您提供与指针完全相同的功能,并且可以与vector一起使用。 I'd go with something like this:
我会选择这样的东西:
void concat_new( std::vector<T> & x ){
auto it = x.begin();
f(x);
it += m;
g(x);
it += n;
...
}
With it, f and g would be like this: 有了它,f和g将像这样:
void f_new( std::vector<T>::iterator x );
void g_new( std::vector<T>::iterator x );
The thing that is great about it - You would not need any further changes in code if You did no evil pointer sorcery in the code. 最重要的是-如果您在代码中没有邪恶的指针法术,则无需对代码进行任何进一步的更改。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.