指针是否有可能在没有任何数据副本的情况下由向量拥有?
Is it possible that a pointer gets owned by a vector without any data copy?
如果我有一个 C 类型的原始指针,是否可以从拥有指针数据的相同类型创建一个 std::vector
而无需任何数据复制(仅移动)?促使我问这个问题的是 data()
成员函数的存在 std::vector
这意味着向量的元素连续驻留在内存中的某个地方。
编辑:我必须补充一点,std::make_shared
.
等功能的存在也加强了我的希望
不,std::vector
并非旨在能够 assume/utilize 预先存在的数组作为其内部存储。
是的,前提是您在获取指针之前创建并填充了 向量并且您不会
- 删除任何元素
- 你不会在
vec.size() == vec.capacity() - 1
时添加新元素,这样做将改变元素的地址
示例
#include <iostream>
void fill_my_vector<std::vector<double>& vec){
for(int i=0; i<300; i++){
vec.push_back(i);
}
}
void do_something(double* d, int size)
{ /* ..... */ }
int main(){
std::vector<double> vec;
fill_my_vector(vec);
//You hereby promise to follow the contract conditions, then you are safe doing this
double* ptr;
int ptr_len = vec.size();
ptr = &vec[0];
//call do_something
do_something(ptr, ptr_len);
//ptr will be alive until this function scope exits
}
编辑
如果你的意思是从一个已经创建的数组中管理数据,你不能...vector 管理它自己的数组...它不能取得不是由它创建的数组的所有权class(向量)。
我认为这不可能直接实现,尽管您不是第一个错过此功能的人。没有非 const
data
成员的 std::string
更加痛苦。希望这会在 C++17 中改变。
如果您自己分配缓冲区,则有一个解决方案。只需预先使用 std::vector
即可。例如,假设您有以下 C 风格的函数,
extern void
fill_in_the_numbers(double * buffer, std::size_t count);
那么您可以进行以下操作。
std::vector<double>
get_the_numbers_1st(const std::size_t n)
{
auto numbers = std::vector<double> (n);
fill_in_the_numbers(numbers.data(), numbers.size());
return numbers;
}
或者,如果您不那么幸运并且您的 C 风格函数坚持自己分配内存,
extern double *
allocate_the_buffer_and_fill_in_the_numbers(std::size_t n);
你可以求助于 std::unique_ptr
,但很遗憾。
std::unique_ptr<double[], void (*)(void *)>
get_the_numbers_2nd(const std::size_t n)
{
return {
allocate_the_buffer_and_fill_in_the_numbers(n),
&std::free
};
}
如果我有一个 C 类型的原始指针,是否可以从拥有指针数据的相同类型创建一个 std::vector
而无需任何数据复制(仅移动)?促使我问这个问题的是 data()
成员函数的存在 std::vector
这意味着向量的元素连续驻留在内存中的某个地方。
编辑:我必须补充一点,std::make_shared
.
不,std::vector
并非旨在能够 assume/utilize 预先存在的数组作为其内部存储。
是的,前提是您在获取指针之前创建并填充了 向量并且您不会
- 删除任何元素
- 你不会在
vec.size() == vec.capacity() - 1
时添加新元素,这样做将改变元素的地址
示例
#include <iostream>
void fill_my_vector<std::vector<double>& vec){
for(int i=0; i<300; i++){
vec.push_back(i);
}
}
void do_something(double* d, int size)
{ /* ..... */ }
int main(){
std::vector<double> vec;
fill_my_vector(vec);
//You hereby promise to follow the contract conditions, then you are safe doing this
double* ptr;
int ptr_len = vec.size();
ptr = &vec[0];
//call do_something
do_something(ptr, ptr_len);
//ptr will be alive until this function scope exits
}
编辑
如果你的意思是从一个已经创建的数组中管理数据,你不能...vector 管理它自己的数组...它不能取得不是由它创建的数组的所有权class(向量)。
我认为这不可能直接实现,尽管您不是第一个错过此功能的人。没有非 const
data
成员的 std::string
更加痛苦。希望这会在 C++17 中改变。
如果您自己分配缓冲区,则有一个解决方案。只需预先使用 std::vector
即可。例如,假设您有以下 C 风格的函数,
extern void
fill_in_the_numbers(double * buffer, std::size_t count);
那么您可以进行以下操作。
std::vector<double>
get_the_numbers_1st(const std::size_t n)
{
auto numbers = std::vector<double> (n);
fill_in_the_numbers(numbers.data(), numbers.size());
return numbers;
}
或者,如果您不那么幸运并且您的 C 风格函数坚持自己分配内存,
extern double *
allocate_the_buffer_and_fill_in_the_numbers(std::size_t n);
你可以求助于 std::unique_ptr
,但很遗憾。
std::unique_ptr<double[], void (*)(void *)>
get_the_numbers_2nd(const std::size_t n)
{
return {
allocate_the_buffer_and_fill_in_the_numbers(n),
&std::free
};
}