如何动态分配一个长度为10的int数组对象?

8
很明显这样做是不行的,因为它被解释为分配一个int数组:
int (*ptr)[10] = new int[10];

令人惊讶的是,这种方法也不起作用:
typedef int arr10[10];
arr10 *ptr = new arr10;

这个是有效的:

ptr = new int[1][10];

但它使用new[]而不是new

出于我的好奇心,是否可能使用new来分配类型为int[10]的单个对象,而不是使用new[]来分配10个对象的数组或一个int[10]对象的数组?


4
你在做什么,而且最重要的是为什么? - Karoly Horvath
3
你需要什么?10个整数?那new int[10];有什么问题吗?请问还需要什么? - Karoly Horvath
分配数组时使用new而不是new[]的原因是什么? - 101010
10
这是一个有趣的问题,因为它试图理解数组的本质。提问者显然并不是出于实际目的而提问,而是出于兴趣询问。因此,建议使用 std::vectorstd::array 看起来不太合适。 - Christian Hackl
5
@ChristianHackl:建议使用std::vectorstd::array永远不会错,但我明白你的意思。;-) - DevSolar
1
-1 下降是因为 OP 在评论中声明,使用纯非数组new分配数组的 C++ 方法,即将其放在一个struct中,不是他关于如何实现它的问题的答案。这意味着此问题存在隐藏的限制。无法知道对 OP 而言什么才是可接受的。 - Cheers and hth. - Alf
5个回答

7
这是不可能的。在C++中,数组没有一流对象语义,例如它们不能被传递给函数或从函数返回。
您可以在C++11中使用std :: array。它有许多优点:对象语义,调试模式下的索引检查,迭代器和STL接口,size()方法,无隐式指针转换。当您有C++11编译器时,几乎没有理由再使用旧的C数组了。
*仅可以传递元素的指针或指向数组的指针/引用。

3
我可以向您保证,您的回答绝不是琐碎的。 - Karoly Horvath

3

一种方法是在不完美的类型系统规则内工作:1

auto main() -> int
{
    using Ten_ints = int [10];
    Ten_ints* p_ints = []() -> Ten_ints*
    {
        struct Wrapper{ Ten_ints a; };
        return &(new Wrapper)->a;
    }();
    (void) p_ints;
}

更直接的方式是主动掌握事情的控制:
auto main() -> int
{
    using Ten_ints = int [10];
    Ten_ints* p_ints = reinterpret_cast<Ten_ints*>( new Ten_ints );
    (void) p_ints;
}

第一个代码片段按照此答案结尾处所引用的原问题执行,使用普通的“new”而不是“new[]”来分配对象。第二个代码片段展示了使用“new[]”的最自然方式。OP建议的“new int [1] [10]”是另一种方法(因此是获取数组指针的第三种方法),具有在类型系统中工作的优点,但缺点是不太明显。总之,“当然”的答案是可以使用[非数组]“new”来分配类型为“int [10]”的单个对象。
注1:标准保证POD结构体开头没有填充。实际上这意味着解除分配同样不是问题。但从正式上讲,需要对应用于分配的类型进行相同类型的解除分配。

3
auto main() -> int 让我感到悲伤...也许我只是一个愚顽的老人,但我并不明白为什么要加入lambda表达式、不必要的尾置返回类型和随机结构体来解释如何使用 new 创建数组。那些连 new 都用不好的人又怎么能理解这些呢? - JPhi1618
4
我不理解为什么你要使用这么多代码,当这个问题只是关于如何使用 new 的基础问题。我不知道你回答了什么问题,以及创造一个包含局部变量的结构体并创建一个 lambda 函数来调用该结构体的 new 方法有什么解决之处。这是一个初学者的问题,而你似乎尝试用最复杂的方式解决它。另外,“难过”只是在开玩笑——我不应该给评论加任何轻浮的色彩。 - JPhi1618
3
除了作为“现代 C++”特性的一个小动物园之外,这几乎与OP列出的typedef int arr10 [10];解决方案完全相同。 - Grault
1
@Hurkyl:你选择的答案开头是“这是不可能的”,这显然是错误的。也许这里没有一个真正好的答案。但如果可能的话,撤销你的选择会很好,因为它会误导所有通过谷歌来到这里的读者。 - Cheers and hth. - Alf
2
@Cheers:在我看来,你的回答并没有回答我所问的问题。我没有投反对票,因为我认为这是对一个相关问题的公正观察,但如果以任何方式暗示它是我实际提出的问题是可行的,那就会产生误导。 - user1084944
显示剩余9条评论

2
new int[10]会分配一个类型为int[10]的单个对象,也就是一个由10个int组成的数组。但是,此表达式的返回值是指向该数组第一个元素的指针。引用C++14,5.3.4/5中的话:

当分配的对象是一个数组(即使用了noptr-new-declarator语法或new-type-idtype-id表示数组类型时),new-expression将产生指向数组初始元素(如果有)的指针。[注意:new intnew int[10]都具有类型int*,而新的int[i][10]的类型为int (*)[10]——结束说明]


2

您正在分配对象数组。

T[10] 是 10 个对象,而不是一个。实际上,它是 十一个 对象--一个包含 10 个 T 对象的数组(类型为 array of 10 T)。

这需要对每个 T 进行构造函数调用,并在数组被 delete 的时候进行相应的析构函数调用,这就是为什么数组需要使用 new[]delete[]如果您试图绕过这一点,那么您的代码将会出错。

因此:

int * ptr = new int[10];

// ...

delete [] ptr;

或者使用Boost(因为裸指针既丑陋又容易出错):
boost::shared_array< int > ptr( new int[10] );

// ...

或者(因为并非每个人都喜欢Boost,而且标准已经给我们带来了<array>):

std::array< int, 10 > a;

// ...

或者使用老牌的 <vector>:

std::vector< int > v( 10 );

// ...

@thab:没错。我随意使用了std::shared_ptr(仍然与C++11之前的boost::shared_array链接),并且完全搞反了。 - DevSolar
我认为区分由_C++类型_ T[size]表示的数组和作为_连续数据结构_的数组概念很重要,因为它可以在std::vector、由std::malloc()new[]分配的内存中找到。 - TheOperator

2
< p > new运算符为一种类型分配一个元素的内存。这就是它的工作方式。如果您想分配多个元素的序列,则需要使用数组运算符并指定要使用的元素数量new int[5]。如果您真的想做这样的事情,可以定义一个结构体并在其上设置一个数组。因此,在调用新函数之后,这将分配数组本身。

typedef struct TEST{
    int testInt[5];
};

TEST* myVarTest = new TEST();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接