我有一个返回std::vector<float>
的C ++函数。
我正在与一些C代码接口。
如何更改此C ++函数以便返回指向float数组的指针,如何保存此返回的数组以便在C代码中使用它?
答案 0 :(得分:5)
如果C ++ 11不可用,您可以使用std::vector::data
或&my_vector[0]
获取指向“原始”数组的指针。但是,如果向量操作强制向量调整大小,则原始存储将在内存中移动,并且此指针将不再安全使用。如果任何可能发生这种情况,您将需要分配单独的存储空间(例如,通过创建vector
的副本)并提供指向该存储空间的指针。
更新:伍德罗的评论让我注意到你实际上是在从函数返回一个指针之后。您只能返回指向堆分配内存的指针,因此您无法使用本地vector
(或任何其他类型的堆栈分配内存)来执行此操作。
答案 1 :(得分:1)
从C的角度来看,vector<float>
做了两件事:
因为2是C的外星概念(没有什么事情会自动发生,当然不会释放内存),所以没有简单的替代品。基本上你有三个选择。它们与你希望函数在C中“返回字符串”时的三个选项相同,虽然这里我们需要告诉调用者指针和长度。
在我看来,第三种选择是“正确的答案”,因为它是你在设计中首先尝试的那种,如果设计看起来不错,你会坚持下去。第一个和第二个可以作为方便函数提供,以便调用代码真正受益于它们,或者包裹在第三个或与第三个一起。
size_t c_wrapper(float **pResult) {
try {
std::vector<float> vec(cpp_function());
*pResult= (float*) std::malloc(vec.size() * sizeof(float));
if (!*pResult) { /* handle the error somehow */ }
std::copy(vec.begin(), vec.end(), *pResult);
return vec.size();
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
上行:简单的呼叫代码。
下行:调用者必须free
内存,即使事先知道大小并且数据很适合本地数组变量。由于内存分配,可能会很慢。
型号:strdup
(Posix)
见jrok的回答:
size_t c_wrapper(float **pResult) {
try {
static std::vector<float> vec;
vec = cpp_function(); // or cpp_function().swap(vec) in C++03
*pResult = &vec[0];
return vec.size();
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
上行:可靠的简单呼叫代码。
下行:程序中只有save
的一个实例,因此返回的指针只指向正确的数据,直到下次调用c_wrapper
为止。特别是,这非常不安全。如果结果非常大,那么从调用者不再需要它之前就会浪费该内存,直到下次调用该函数为止。
型号:strtok
,gethostbyname
。
size_t c_wrapper(float *buf, size_t len) {
try {
std::vector<float> vec(cpp_function());
if (vec.size() <= len) {
std::copy(vec.begin(), vec.end(), buf);
}
return vec.size()
} catch (std::bad_alloc) { /* handle the error somehow */ }
}
上行:最灵活。
下行:调用者必须传入一个足够大的缓冲区(假设cpp_function
表现一致,调用者可以通过调用大小为0的函数和空指针找到大小,从某处获得足够大的缓冲区,然后再次调用该函数。)
模型:strcpy
,snprintf
,getaddrinfo
。
答案 2 :(得分:0)
#include <vector>
#include <iostream>
int main()
{
std::vector<float> vec;
vec.push_back(1.23);
vec.push_back(3.123);
int len = vec.size();
float *arr = new float[len];
std::copy(vec.begin(),vec.end(),arr);
for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i){
std::cout << arr[i] << "\n";
}
delete [] arr;
return 0;
}
答案 3 :(得分:0)
您可以将返回的临时矢量保存在具有静态存储持续时间的矢量对象中。
std::vector<float> foo()
{
return std::vector<float>();
}
float* call_foo_and_get_pointer()
{
static std::vector<float> save; // this line is executed only at the first
// call to enclosing function
save = foo();
return save.data(); // or &data[0]
}
从call_foo_and_get_pointer
返回的指针保证在下次调用之前保持有效。