【问题标题】:Can't & proper way to declare an array of arrays of int in class member c++11无法在类成员 c++11 中声明 int 数组的正确方法
【发布时间】:2017-12-01 23:41:08
【问题描述】:

我正在制作一个定义大小作为参数的简单地图,我希望将其存储在我的私有成员变量中。

我将展示一个简单的例子:

class A {
   public:
   A (const int size) {
     map_size_ = size;
     //or | both will not compile
     int map[size][size];


   }
   private:
    int map_size_;
    int map_[map_size_][map_size_];
}

我知道 map_ 不会编译,但我想知道如何使用构造函数参数中的 const int 且不使用指针正确声明它。

【问题讨论】:

    标签: c++ arrays c++11 int


    【解决方案1】:

    你应该使用std::vector

    #include <vector>
    
    class A {
    public:
        explicit A (const int size) {
             map_.resize(size);
             for (auto &v : map_) v.resize(size);
        }
    
    private:
        std::vector<std::vector<int>> map_;
    };
    

    从性能的角度来看,这可能不是最佳方式,但它是最简单的方式。没有办法解决这个问题。 int[][] 声明不适用于 C++ 中的非编译时值。

    提示:

    • explicit 与单参数构造函数一起使用。
    • 您应该使用std::size_t 而不是int 作为尺寸。

    【讨论】:

    • 我喜欢用for-each,很干净。
    • 构造函数中不必使用resize()。直接用需要的大小直接构造向量,而不是依赖默认构造然后调整大小。
    • @Eljay 非常干净,但完全没有必要。如果您利用成员初始化器列表,vector 将为您免费完成所有这些工作。
    • @user4581301 不会。如果您建议使用map_(size, std::vector&lt;int&gt;(size)),那么我必须说这是一个可怕的想法。它不会是免费的,因为这个向量将被复制并且复制数据比 memsetting 它慢。另外,std::vector 在大分配时已经非常慢,因为它在从内核分配零页后无法避免内存初始化。
    • 从来没有遇到过问题,但可能是因为如果我需要速度,我不会分配vectors 的vector。我会做@Eljay 所做的事情,但使用vector。如果我不能容忍零初始化的成本,我会忽略询问者的无指针请求,并且几乎完全按照 Eljay 的建议去做。
    【解决方案2】:

    这应该可行:

    class A {
    public:
      A(int const size) {
        _map_size = size;
        _map = new int[_map_size * _map_size];
       }
    private:
      int _map_size;
      int* _map;
    };
    

    更新 - 显然人们想要一个比 OP 要求的更全面的解决方案。

    class A {
    public:
      A(int const size)
        : _map_size(size)
        , _map(new int[_map_size * _map_size]) {
       }
      A(A const&) = delete;
      ~A() {
        delete[] _map;
      }
      A& operator=(A const&) = delete;
      int at(int x, int y) const {
        if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
          throw "That coordinate is in the giggleweeds";
        return _map[y * _map_size + x];
      }
      int set_at(int x, int y, int value) {
        if (x < 0 || x >= _map_size || y < 0 || y >= _map_size)
          throw "That coordinate is in the giggleweeds";
        _map[y * _map_size + x] = value;
      }
    private:
      int _map_size;
      int* _map;
    };
    

    【讨论】:

    • 扔字符串?你一定是在开玩笑吧!为什么需要set_at?只需标准 int &amp;at 即可!
    • @Ivan • 用户需求在这一点上相当稀少。
    • atsetAt 更通用一点:int &amp; operator()(size_t x, size_t y) { if (x &lt; _map_size &amp;&amp; y &lt; _map_size) { return _map[y * _map_size + x] ;} throw std::out_of_range("That coordinate is in the giggleweeds"); }
    • @user4581301 • 如果遵循标准库约定,则应选中 at() 函数,而应取消选中 (x,y) 仿函数。
    • 我同意这一点。两者可能都应该有const 版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-15
    • 2014-03-06
    相关资源
    最近更新 更多