我正在与需要类型为float**
的2D数组的C库接口,其大小在运行时确定。我想使用STL容器(如std :: vector)来管理此内存,但vector<vector<float>>::data()
提供vector<float>*
,而不是float**
。我该怎么办?
答案 0 :(得分:3)
您可以创建一个新的向量,其中包含指向向量矢量 的内部向量所管理的所有内部数组的指针:< / p>
<强>输出:强> 注意:强> 显然,如果更改矢量,则需要重建指针矢量,因为地址可能会发生变化。 您可以通过一些包装函数动态重建它,如下所示: 或者(我最喜欢的)构建一个包装器void old_c_function(float** floats, std::size_t X, std::size_t Y)
{
for(auto x = 0U; x < X; ++x)
for(auto y = 0U; y < Y; ++y)
std::cout << "[" << x << ", " << y << "] = " << floats[x][y] << '\n';
}
int main()
{
std::vector<std::vector<float>> v =
{
{1.2, 3.4, 5.6},
{7.8, 9.0, 1.2},
};
// create a new vector to hold the pointers to the arrays
// managed by the internal vectors
std::vector<float*> v_ptrs;
v_ptrs.reserve(v.size());
// add the addresses of all the arrays to the new vector
std::for_each(std::begin(v), std::end(v),
[&v_ptrs](auto& v){ v_ptrs.push_back(v.data()); });
// call your legacy function using your pointer vector
old_c_function(v_ptrs.data(), v.size(), v.front().size());
}
[0, 0] = 1.2
[0, 1] = 3.4
[0, 2] = 5.6
[1, 0] = 7.8
[1, 1] = 9
[1, 2] = 1.2
void new_wrapper_function(std::vector<std::vector<float>>& v)
{
// create a new vector to hold the pointers to the arrays
// managed by the internal vectors
std::vector<float*> v_ptrs;
v_ptrs.reserve(v.size());
// add the addresses of all the arrays to the new vector
std::for_each(std::begin(v), std::end(v)
[&v_ptrs](auto& v){ v_ptrs.push_back(v.data()); });
// call your legacy function using your pointer vector
old_c_function(v_ptrs.data(), v.size(), v.front().size());
}
class
来封装两个向量,并在主要向量在其中一个维度上增加时更新指针向量。
答案 1 :(得分:0)
我会说使用
typedef std::pair<int, int> shape;
std::pair<float **, shape> obj;
或
std::tuple<float **, int, int> obj;
无论你喜欢什么。
答案 2 :(得分:0)
我该怎么办?
a)使用1d载体
typedef std::vector<float> FloatVec_t
b)要访问1D向量,您可以从2d坐标计算1d索引,这是一个可以优化的简单函数。
// size_t maxCol; is runtime size info
size_t indx1D(size_t r, size_t c)
{ return static_cast<size_t>((r*maxCol) + c); }
c)为2d访问创建/使用getElement(x,y):
FloatVec_t fltVec1D;
// 2d access
float* getElement(size_t r, size_t c) { return (fltVec [indx1D (r,c)]); }
d)在1D向量之上创建arr。请参阅下面的工作代码。
环境:
Ubuntu 15.10; g ++版本5.2.1 20151028;老戴尔Athlon
代码/ MCVE:
#include "../../bag/src/dtb_chrono.hh"
#include <iostream>
#include <iomanip>
#include <vector>
#include <cassert>
typedef std::vector<float> FloatVec_t;
class T537_t
{
private:
FloatVec_t fltVec1D;
size_t maxCol;
size_t maxRow;
public:
T537_t () = default;
~T537_t() = default;
int exec(size_t a_MaxCol,
size_t a_MaxRow)
{
maxCol = a_MaxCol;
maxRow = a_MaxRow;
size_t N = maxCol * maxRow;
std::cout << "\n sizeof(float): " << sizeof(float) << std::endl;
std::cout << "\n Col x Row: " << maxCol << " x " << maxRow
<< " = " << N
<< "\n\n reserved " << N << " elements in 1D vec" << std::endl;
fltVec1D.reserve(N);
std::cout << "\n initialize 1D vec with values computed from row and col" << std::flush;
for (uint r=1; r<=maxRow; ++r)
for (uint c=1; c<=maxCol; ++c)
fltVec1D.push_back (100.1F * static_cast<float> (((r-1)*maxCol) + c));
std::cout << "\n\n report fltVec1D addrs: " << std::flush;
for (uint r=0; r<maxRow; ++r)
{
std::cout << "\n fltVec1D[" << std::setw(2) << r << "] " << std::flush;
for (uint c=0; c<maxCol; ++c)
std::cout << " " << std::setw(8)
<< &fltVec1D[indx1D(r,c)] << std::flush;
std::cout << std::flush;
}
std::cout << "\n\n report fltVec1D data: " << std::flush;
for (uint r=0; r<maxRow; ++r)
{
std::cout << "\n fltVec1D[" << std::setw(2) << r << "] " << std::flush;
for (uint c=0; c<maxCol; ++c)
std::cout << " " << std::setw(8) << std::setprecision(5)
<< fltVec1D[indx1D(r,c)] << std::flush;
std::cout << std::flush;
}
// overlay arr on top of fltVec1D data
float** arr = new float* [maxRow]; // arr contains rows
{
for (size_t r=0; r < maxRow; ++r)
arr[r] = getElement(r,0); // rows already exist
} // and start at col 0,
std::cout << "\n\n report arr data: " << std::flush;
for (size_t r=0; r<maxRow; ++r)
{
std::cout << "\n arr[" << std::setw(2) << r << "] " << std::flush;
for (size_t c=0; c<maxCol; ++c)
{
std::cout << " " << std::setw(8) << std::setprecision(5)
<< arr[r][c] << std::flush;
}
std::cout << std::flush;
}
std::cout << "\n\n\n report address diffs: &arr[r][c] - getElement(r,c) : \n" << std::flush;
for (uint r=0; r<maxRow; ++r)
{
std::cout << "\n row" << std::setw(2) << r << " " << std::flush;
for (uint c=0; c<maxCol; ++c)
{
float* addr1 = & arr[r][c];
float* addr2 = getElement(r,c);
std::cout << " " << std::setw(8) << (addr1 - addr2) << std::flush;
}
std::cout << std::flush;
}
delete[] arr; // delete of float** arr = new float* [maxCol];
return 0;
}
private: // methods
size_t indx1D(size_t r, size_t c)
{
assert(r<maxRow);
assert(c<maxCol);
return static_cast<size_t>((r*maxCol) + c);
}
float* getElement(size_t r, size_t c) { return (& fltVec1D [indx1D(r,c) ] ); }
}; // class T537_t
int main(int argc, char* argv[])
{
if(argc > 1)
{
std::cout << "\nargc: " << argc << std::endl;
for (int i = 0; i < argc; i += 1) std::cout << argv[i] << " ";
std::cout << std::endl;
}
if(3 != argc) {
std::cerr << "\n 2 Required parameters: maxCol maxRow " << std::endl;
return (0);
}
setlocale(LC_ALL, "");
std::ios::sync_with_stdio(false);
int retVal = -1;
{
T537_t t537;
Time_t start_us = HRClk_t::now();
retVal = t537.exec(static_cast<size_t>(std::atoi(argv[1])), // col - i.e. 5
static_cast<size_t>(std::atoi(argv[2]))); // row - i.e. 20
auto duration_us = std::chrono::duration_cast<US_t>(HRClk_t::now() - start_us);
std::cout << "\n\n t537.exec() duration " << duration_us.count() << " us" << std::endl;
}
return(retVal);
}
命令行参数的输出示例3 5
sizeof(float): 4
Col x Row: 3 x 5 = 15
reserved 15 elements in 1D vec
initialize 1D vec with values computed from row and col
report fltVec1D addrs:
fltVec1D[ 0] 0x179dc50 0x179dc54 0x179dc58
fltVec1D[ 1] 0x179dc5c 0x179dc60 0x179dc64
fltVec1D[ 2] 0x179dc68 0x179dc6c 0x179dc70
fltVec1D[ 3] 0x179dc74 0x179dc78 0x179dc7c
fltVec1D[ 4] 0x179dc80 0x179dc84 0x179dc88
report fltVec1D data:
fltVec1D[ 0] 100.1 200.2 300.3
fltVec1D[ 1] 400.4 500.5 600.6
fltVec1D[ 2] 700.7 800.8 900.9
fltVec1D[ 3] 1001 1101.1 1201.2
fltVec1D[ 4] 1301.3 1401.4 1501.5
report arr data:
arr[ 0] 100.1 200.2 300.3
arr[ 1] 400.4 500.5 600.6
arr[ 2] 700.7 800.8 900.9
arr[ 3] 1001 1101.1 1201.2
arr[ 4] 1301.3 1401.4 1501.5
report address diffs: &arr[r][c] - getElement(r,c) :
row 0 0 0 0
row 1 0 0 0
row 2 0 0 0
row 3 0 0 0
row 4 0 0 0
要点:
此单元测试代码演示:
a)构建并初始化1d std :: vector。
b)使用内置数组结构和new。
创建“float ** arr”c)使用getElement(r,0)快速循环加载每个行指针。
d)单元测试显示来自1d vec(fltVec1D)和arr
的相同信息(地址和数据)e)测试通过比较两个名称提供访问相同地址的地址以及相同数据的地址来结束。
“arr”适合传递给遗留功能(未经测试)。