新的int [] []在C ++中是否有效?

时间:2015-10-03 10:06:23

标签: c++ c++11

我遇到了一些使用以下方法分配二维数组的代码:

auto a = new int[10][10];

这在C ++中是否有效?我搜索了几本C ++参考书,但没有人提到这种方法。 通常我会手动完成分配,如下所示:

int  **a = new int *[10];
for (int i = 0; i < 10; i++) {
    a[i] = new int[10];
}

如果第一种方法有效,那么首选哪种方法?

3 个答案:

答案 0 :(得分:19)

第一个例子:

auto a = new int[10][10];

多维数组数组数组分配为连续的内存块。

第二个例子:

int** a = new int*[10];
for (int i = 0; i < 10; i++) {
    a[i] = new int[10];
}

这不是真正的多维数组。事实上,它是一个指针数组,需要两个间接来访问每个元素。

答案 1 :(得分:4)

表达式new int[10][10]意味着分配一个包含10个int[10]类型元素的数组,所以是的,这是一个有效的事情。

new返回的指针类型为int(*)[10];可以通过int (*ptr)[10];声明一个这种类型的变量。

为了易读性,可能不应该使用该语法,并且应该优先使用示例中的auto,或者使用typedef进行简化,如

中所示。
using int10 = int[10]; // typedef int int10[10];
int10 *ptr;

答案 2 :(得分:1)

在这种情况下,对于小型数组,在堆栈上分配它们会更有效。甚至可能使用诸如std::array<std::array<int, 10>, 10>之类的便利包装器。但是,一般来说,执行以下操作是有效的:

auto arr = new int[a][b];

其中astd::size_tbconstexpr std::size_t。这样可以提高分配效率,因为operator new[]只需要调用sizeof(int) * a * b作为参数,而不是a调用operator new[] sizeof(int) * b作为论点。正如Galik在他的回答中所说,由于缓存一致性增加(整个阵列在内存中是连续的),因此还有可能缩短访问时间。

然而,我可以想象使用这样的东西的唯一原因是使用编译时大小的矩阵/张量,其中所有维度在编译时都是已知的,但如果它超过了堆,则在堆上分配堆栈大小。

一般情况下,最好编写自己的RAII包装类,如下所示(您还需要为高度/宽度添加各种访问器,以及实现复制/移动构造函数和赋值,但一般的想法在这里:

template <typename T>
class Matrix {
public:
     Matrix( std::size_t height, std::size_t width ) : m_height( height ), m_width( width )
     {
           m_data = new T[height * width]();
     }

     ~Matrix() { delete m_data; m_data = nullptr; }

public:
     T&               operator()( std::size_t x, std::size_t y )
     {
          // Add bounds-checking here depending on your use-case
          // by throwing a std::out_of_range if x/y are outside 
          // of the valid domain.
          return m_data[x + y * m_width];
     }

     const T&         operator()( std::size_t x, std::size_t y ) const
     {
          return m_data[x + y * m_width];
     }

private:
     std::size_t      m_height;
     std::size_t      m_width;
     T*               m_data;
};