如何廉价地将c风格数组赋值给std::vector
How to cheaply assign C-style array to std::vector?
目前我做的是:
// float *c_array = new float[1024];
void Foo::foo(float *c_array, size_t c_array_size) {
//std::vector<float> cpp_array;
cpp_array.assign(c_array, c_array + c_array_size);
delete [] c_array;
}
如何优化这个赋值?我不想执行元素复制,而只是交换指针。
当前的std::vector
不提供任何功能或接口来获取先前分配的存储的所有权。如果不小心传入一个堆栈地址,可能会导致更多的问题。
如果你想避免复制到vector中,你要么需要在整个调用链中使用vector,要么在整个调用链中使用C方式使用float[]
。你不能把它们混在一起。可以保证&vec[0]
与c数组是等价的,但是是完全连续的,所以在整个程序中使用vector是可行的。
目前,std::vector
接口不具备从其他std::vector
移动或交换的能力。
唯一的方法是创建一个自定义分配器。
-
写一个可以用数组初始化的分配器类
-
使用分配器作为实参实例化vector
不太可能——这是相当危险的,因为std::vector不知道内存是如何分配的,也不知道应该如何释放。
如果可能的话,你可以用创建一个正确大小的std::vector来代替原来的分配。它使用连续的内存区域,所以它可以代替手动分配的缓冲区。
可以使用自定义分配器。我用clang和gcc检查了godbolt.org。对我来说,这看起来有点难看——但它至少可以作为一个概念的证明。
当然,你必须自己考虑数组的生命周期。
#include <vector>
#include <iostream>
// custom allocator
template <typename T>
class my_allocator {
private:
T* const addr;
public:
template <typename U>
struct rebind {
typedef my_allocator<U> other;
};
//provide the required no-throw constructors / destructors:
constexpr my_allocator(T* addr_) : addr(addr_) { };
constexpr my_allocator(const my_allocator<T>& rhs) : addr(rhs.addr) { };
template <typename U>
my_allocator(const my_allocator<U>& rhs, T* addr_) : addr(addr_) { };
~my_allocator() { };
//import the required typedefs:
using value_type=T;
using pointer=T*;
using reference=T&;
using const_pointer=const T*;
using const_reference=const T&;
using size_type=size_t;
using difference_type=ptrdiff_t;
constexpr pointer allocate(size_type n, const void * = 0) {
pointer t=addr;
std::cout
<< " used my_allocator to allocate at address "
<< t << " (+)" << std::endl;
return addr;
}
constexpr void deallocate(void* p, size_type) {
if (p) {
std::cout
<< " used my_allocator to deallocate at address "
<< p << " (-)" <<
std::endl;
}
}
template< class U, class... Args >
void construct( U* p, Args&&... args ) {
// avoids initialisation of the elements.
std::cout << "Contruct called" << std::endl;
}
};
// helper function for easy useage
template<typename T>
const std::vector<T, my_allocator<T> > CreateVectorFromArray(T* array, int size) {
const my_allocator<T> alloc=my_allocator<T>(array);
std::vector<int, my_allocator<int> > vecAll(size, my_allocator<int>(array));
return vecAll;
}
template<typename T>
using element_type_t = std::remove_reference_t<decltype(*std::begin(std::declval<T&>()))>;
template<typename AR>
auto CreateVectorFromArrayAr(AR& array) {
using T=element_type_t<AR>;
const my_allocator<T> alloc=my_allocator<T>(array);
std::vector<T, my_allocator<T> > vecAll(sizeof(array)/sizeof(array[0]), my_allocator<T>(array));
return vecAll;
}
int main() {
int array[]={0,1,2,3,4,5,6,7,8,9};
std::cout << "Array: " << &array[0] << " " << array[0] << " " << array[1]<< " " << array[2] << std::endl;
auto vecAll=CreateVectorFromArray(array, sizeof(array)/sizeof(array[0]));
auto vec3=CreateVectorFromArrayAr(array);
std::cout << "Vector: " << &vecAll[0] << " " << vecAll[0] << " " << vecAll[1]<< " " << vecAll[2] << std::endl;
std::cout << "Array: " << &array[0] << " " << array[0] << " " << array[1] << " " << array[2] << std::endl;
std::cout << "vec3: " << &vec3[0] << " " << vec3[0] << " " << vec3[1] << " " << vec3[2] << std::endl;
std::cout << "sizeof(vecAll)=" << sizeof(vecAll) << std::endl;
std::cout << "sizeof(void*)=" << sizeof(void*) << std::endl;
return 0;
}
相关文章:
- 为std::string的某个索引赋值
- 使用重载 [] 运算符返回 std::map() 的可赋值
- 使用赋值运算符复制 std::vector
- 将"std::string {aka std::basic_string}"赋值中的不兼容类型<char>
- 非模板 std::reference_wrapper赋值运算符和模板构造函数
- std::constexpr 上下文中的可选赋值运算符
- 对std::unique_ptr数组的赋值
- 派生自 std::exception 的类的赋值运算符
- 重载 std::vector::at 赋值运算符
- C++ std::vector 赋值方法
- 从自身内部替换 std::函数(通过将移动赋值到 *this?)
- std::vector::emplace() 真的在面对抛出移动构造函数/赋值运算符时提供了强大的异常保证吗?
- STL std::map 运算符 [] 在赋值的右侧
- 使用带有下标运算符的赋值运算符将值分配给 std::map
- std::vector 不支持右值赋值
- std::string 的转换运算符无法处理赋值
- std::memcpy或显式字符值赋值-在C++中等于合法
- 输入Std::cin与直接赋值Std::string变量不一样
- 如何从char *赋值std::string
- 如何通过函数赋值std::string