C ++:从vector <vector <t>获取T **&gt;

时间:2017-10-24 01:15:04

标签: c++ stl

我正在与需要类型为float**的2D数组的C库接口,其大小在运行时确定。我想使用STL容器(如std :: vector)来管理此内存,但vector<vector<float>>::data()提供vector<float>*,而不是float**。我该怎么办?

3 个答案:

答案 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”适合传递给遗留功能(未经测试)。