分配2D可变大小的数组

时间:2018-10-03 17:42:50

标签: c++ c++11

我正在尝试将2D可变长度c字符串数组存储到结构中,以便可以通过网络套接字传输和重建它。

计划是在数据包的标题中包含行和列,以帮助我阅读后面的可变大小镜头和arr。我相信我必须在语法上错误地编写指针,否则将它们设置为struct时需要使用某种aux指针。

struct STORAGE {
   int rows;     // hdr
   int cols;     // hdr
   int** lens;
   const char*** arr;
}

// code
int rows = 11;
int cols = 2;

int lens[rows][cols];
const char* arr[rows][cols];
// ... fill with strings ...
// ... along with lens ...

STORAGE store;
store.rows = rows;
store.cols = cols;
store.lens = lens;
store.arr = arr;

编译此代码时出现这些错误:

  

错误:从intint**的无效转换[-fpermissive]

     

错误:分配中无法将const char* [11][2]转换为“ const char ***”

我主要来自Java背景,但我确实了解指针如何工作等等。对于有我背景的人(主要是java / c ++和更少的c语言)来说,这一句的语法有点偏。有什么建议吗?

注意:之所以我不使用更复杂的类型(例如字符串,映射,向量等),是因为我需要通过网络传输结构(即,如果指针的大小可变,则指向堆的指针将无法工作) )。除非有人可以提供更好的解决方案,否则它必须是低级数组。

2 个答案:

答案 0 :(得分:2)

  

除非有人可以提供更好的解决方案,否则它必须是低级数组。

一维std::vector<int>std::vector<uint8_t>已经为您提供了一个使用std::vector::data()成员连续分配的低级数组。

您需要的其他任何尺寸都可以通过适当地分割数据来确定。对于网络传输,您需要预先提供必要的分区尺寸,然后再发送数据。

类似的东西:

Transmit num_of_dimensions
Transmit dim_size_1, dim_size_2, dim_size_3, ...
Transmit data

Receive num_of_dimensions
Loop Receiving dimension sizes
Receive dim_size_1 * dim_size_2 * dim_size_3 * ... of data

我可能要处理的情况是一个看起来像这样的类/结构:

template<typename T>
class MultiDimensional {
    size_t num_dimensions_; // If known in advance can be made a template parameter also
    std::vector<size_t> dimension_sizes_;
    std::vector<T> data_;
public:
    const T& indexing_accessor(...) const;
    T& indexing_accessor(...);
    std::vector<uint8_t> render_transmision_data();
    // construct from transmission data
    MultiDimensional(std::vector<uint8_t>& transmission_data); 
};

答案 1 :(得分:0)

使用诸如数组之类的低级东西不会对您有太大帮助,因为它已经太复杂了。此外,它还会使您陷入兼容性问题的困境(例如考虑字节顺序)。

除非您有非常严格的性能限制,否则请使用专门为联网设计的解决方案:protocol buffers。对于您的情况来说,这有点过头了,但是如果您需要添加任何内容,它可以很好地扩展。

要使用协议缓冲区,请先在.proto文件中定义“消息”(结构),然后使用Proto编译器将它们编译为C ++。

您可以这样定义您的消息(这是一个完整的.proto文件):

syntax = "proto2";

package test;

message Storage {
   message Row {
       repeated string foo = 1;
   }
   repeated Row row = 1;
}

没有直接支持2D数组的方法,但是数组的数组就可以了(repeated意味着给定字段中可以有多个值,它基本上是一个向量)。如果需要快速访问它们,可以添加用于数组大小的字段,但是在大多数实际情况下,检查重复字段的大小就足够了。

获得的是一类具有所需所有字段,负责内存管理并具有a bunch of methods to serialize and deserialize的类。

由于需要使用getter和setter,因此C ++代码的使用时间会更长一些,但是您无需考虑序列化这一事实就可以很好地抵消它-它本身就可以发生。

在C ++中使用此东西的示例可能看起来像这样:

#include "test.pb.h"  // Generated from test.proto

using ::test::Storage;

int main() {
  Storage s;
  Storage::Row* row1 = s.add_row();
  row1->add_foo("foo 0,0");
  row1->add_foo("foo 0,1");
  Storage::Row* row2 = s.add_row();
  row2->add_foo("foo 1,0");
  row2->add_foo("foo 1,1");

  assert(s.row_size() == 2);
  assert(s.row(0).foo_size() == 2);

  s.PrintDebugString();  // prints to stdout
}

在结果中,您将获得以下输出(请注意,这是调试输出,而不是实际的序列化):

row {
  foo: "foo 0,0"
  foo: "foo 0,1"
}
row {
  foo: "foo 1,0"
  foo: "foo 1,1"
}

出于完整性考虑:在上面的示例中,源文件为test.prototest.cpp,使用以下文件进行编译:

protoc --cpp_out=. test.proto
g++ test.cpp test.pb.cc -o test -lprotobuf