Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:从向量中获取T**<;向量<;T>&燃气轮机;_C++_Stl - Fatal编程技术网

C++ C++;:从向量中获取T**<;向量<;T>&燃气轮机;

C++ C++;:从向量中获取T**<;向量<;T>&燃气轮机;,c++,stl,C++,Stl,我正在与一个C库接口,它需要一个类型为float**的2D数组,其大小在运行时确定。我想使用std::vector之类的STL容器来管理这个内存,但是vector::data()给出的是vector*,而不是float**。我能做什么?我会说使用 typedef std::pair<int, int> shape; std::pair<float **, shape> obj; typedef标准::成对形状; std::对obj; 或 std::元组对象; 你喜欢

我正在与一个C库接口,它需要一个类型为
float**
的2D数组,其大小在运行时确定。我想使用std::vector之类的STL容器来管理这个内存,但是
vector::data()
给出的是
vector*
,而不是
float**
。我能做什么?

我会说使用

typedef std::pair<int, int> shape;
std::pair<float **, shape> obj;
typedef标准::成对形状;
std::对obj;

std::元组对象;
你喜欢什么都行

我能做什么

a) 使用一维向量

 typedef std::vector<float> FloatVec_t
d) 在1D向量的顶部创建arr。请参阅下面的工作代码

环境:

Ubuntu 15.10;g++版本5.2.1 20151028;老戴尔·阿龙

代码/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);
}
总结:

此单元测试代码演示了:

a) 构建并初始化1d std::vector

b) 使用内置数组构造和新数组创建“float**arr”

c) 快速for循环使用getElement(r,0)加载每个行指针

d) 单元测试显示来自1d vec(fltVec1D)和arr的相同信息(地址和数据)

e) 测试通过比较地址来结束,这表明这两个名称提供了对相同地址的访问,从而提供了相同的数据

“arr”适用于传递给遗留函数(未测试)。

您可以创建一个新的向量,其中包含指向由向量向量的内部向量管理的所有内部数组的指针:

注意:

[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());
}
void新包装函数(std::vector&v)
{
//创建一个新的向量来保存指向数组的指针
//由内部向量管理
std::向量v_ptrs;
v_ptrs.reserve(v.size());
//将所有数组的地址添加到新向量
标准::每个(标准::开始(v),标准::结束(v)
[&v_ptrs](自动&v){v_ptrs.push_back(v.data());});
//使用指针向量调用遗留函数
旧的_c_函数(v_ptrs.data(),v.size(),v.front().size());
}

或者(我最喜欢的)构建一个包装器
来封装这两个向量,并在主向量的某个维度的容量增加时更新指针向量。

分配您自己的
float**
vector
并用指向内部向量的
数据()的指针填充它。你不能免费获得一个
float**
,它只是在你选择的数据结构中不存在。我可以问一下为什么我的问题被否决了吗?我尽量简明扼要地问这个问题,并在发帖前进行了广泛的搜索。我怎么能让它变得更好呢?公认的答案既有趣又深刻。不明白为什么这篇文章不受欢迎…这如何帮助将某些东西传递给需要
浮点**
?通常当函数文档声称
浮点**p
表示mxn 2D数组时,意味着元素是
p[i][j]
其中
i@aschepler-谢谢你的提问和评论。。我决定提供一些代码,并且必须寻找它,然后修改它。。。。然后,您希望C函数只是有一个草率的声明,并实际将其参数视为
float*const*
@aschepler。C函数可以毫无问题地更新数组,指针指向原始数组中的实际数据。将
std::copy
复制到
std::back\u inserter(v)如何
?@aschepler因为我没有复制
浮点值,所以我要获取每个内部数组的第一个元素的地址。噢,糟了。
std::vector
无法很好地初始化
float*
。不。
#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);
}
  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
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());
}