使用 new 运算符创建用户输入大小的数组

Posted

技术标签:

【中文标题】使用 new 运算符创建用户输入大小的数组【英文标题】:Creating a user-inputted sized Array using new operator 【发布时间】:2013-06-09 07:16:58 【问题描述】:

我有几个与数组相关的问题。我研究过数组大小在声明/编译器必须知道它的值时必须是常量。但是使用 GNU GCC 编译器(C++11 标准过滤器),当动态声明所述数组时(使用new),我能够完美地编译和运行使用变量作为数组大小的程序

int num;
cout << "How big an array? ";
cin >> num;
int *arr = new int [num];

问题1) 这被认为是标准的吗?我的教授是矛盾的。

问题2)如果它标准的,那么在这种情况下,是否可以在创建后扩展数组(或任何数组)的大小?

Ques3) 同样,如果这个表达式是标准的,那么是否可以在函数中使用它——例如。使用函数来创建这样的数组? (如果有,怎么做?)

(PS:你好,我是新来的,还是个 C++ 新手)

【问题讨论】:

***.com/a/4984228/497106 你的教授在像动态数组这样简单的事情上是矛盾的? @chris:我怀疑教授们对这个问题的理解不同。 @GregHewgill,这就是我的想法。我敢打赌,他们认为 VLA 是主题(或至少其中之一)。 【参考方案1】:

问题1) 这被认为是标准的吗?我的教授是矛盾的。

是的,这是完全有效的。请注意,您需要使用运算符delete[] 显式删除arr 指向的内存。最好使用std::vector&lt;int&gt;,它会为您执行内存管理。

你可能会误认为可变长度数组(VLA),这是C++中不允许的:

// same num as the one in your example
int arr[num]; // ERROR

这在C 中有效,但在C++ 中无效(C++14 将包含 VLA,尽管它们与 C VLA 会有一些差异)。

问题2)如果是标准的,在这种情况下,是否可以扩展 创建后数组(或任何数组)的大小?

不,您不能扩展它。您可以分配一个更大的数组,复制元素并删除前一个。同样,如果您使用 std::vector&lt;int&gt;,这将自动完成。

问题3) 同样,如果这个表达式是标准的,那么是否有可能 在函数中使用它 - 例如。使用一个函数来创建这样一个 大批? (如果有,怎么做?)

是的,当然:

int *allocate(size_t size) 
    return new int[size];

但是再次使用std::vector

int num;
cout << "How big an array? ";
cin >> num;
std::vector<int> arr(num); // num elements, all of them initialized to 0
// insert 42 at the end. reallocations(if any) are done automatically
arr.push_back(42); 

【讨论】:

谢谢!但是使用 allocate 函数,a) 我的 IDE 将 size 标记为关键字。那么使用(size_t size) 而不是(size_t num)(int num) 有什么特殊意义吗? @user2480471 不,使用size 作为参数名没有错。奇怪的是您的 IDE 会这样做。当然,您可以更改参数的名称,这根本不会改变语义。此外,operator newsize_t 作为其参数,因此最好使用此类型而不是 int 以避免错误/警告。【参考方案2】:

我研究过数组大小在声明时必须是常量/编译器必须知道它的值。

嗯,没错,但仅适用于 staticautomatic 数组。您正在堆上分配一个 动态 数组,这是不同的。

静态数组

在全局范围内声明的数组必须具有恒定大小。

int arr[5];

自动数组

在函数中自动分配的数组必须具有恒定大小(例外情况见下文)。

void f() 
    int arr[5];

动态数组

使用new 在堆上分配的动态数组可以有任何大小、常量或变量。

new int[5];
new int[n * 4];

GCC 扩展

例外是 GCC 允许使用 变量 来声明自动数组的大小:

void f(int n) 
    int arr[n];

但是,这种用法并不标准。

【讨论】:

感谢您解释这个概念!【参考方案3】:

问题1 - operator 'new' 用于动态分配,我的意思是,当你以前不知道数组的大小时,那么,没有问题,你可以做到!我认为您的教授对 C sintax 感到困惑,其中 new 既不存在也不被允许制作如下内容: int p[n];例如。

问题 2 - 不,不可能增加使用 operator new 创建的数组的大小。您必须分配另一个数组并复制数据。您可以考虑使用矢量以便轻松完成。

问题 3 - 我不明白为什么要这样做,但有可能..

int* createarray(int size)

   return new int[size]; 



int main()

    int *p = createarray(10);

【讨论】:

【参考方案4】:

Q1:这算是标准吗?

给定定义 int n = 42, new float[n][5] 是良构的(因为 n 是 a 的表达式 noptr-new-declarator),但新的 float[5][n] 格式错误(因为 n 是 不是常量表达式)。 --5.3.4.6,N3242

如果分配的类型是数组类型,分配函数的 name 是 operator new[] 并且释放函数的名字是 运算符删除[]。 --5.3.4.8,N3242

new T[5] 导致调用 operator new[](sizeof(T)*5+x) 这里,x 和 y 是表示数组分配开销的非负未指定值; --5.3.4.12,N3242

Q2:如果是标准的,那么在这种情况下,是否可以在创建后扩展数组(或任何数组)的大小?

部分不推荐,或不推荐。 当分配函数返回一个非空值时,它必须是一个指向存储块的指针 为对象预留的空间。大部分分配发生在堆中,可能没有更多的连续内存,这对数组很重要。 如果你必须这样做并且有一个内存轮询,使用placement new 操作符你可以部分地做到这一点,但是你现在所做的是分配器的设计者所做的,并且有破坏内部内存存储的风险。

Q3:使用函数创建这样的数组? (如果有,怎么做?)

由 new-expression 创建的实体具有动态存储持续时间 (3.7.4)。 [注:这种实体的生命周期不一定 仅限于创建它的范围。 ——尾注] --5.3.4.1,N3242

剩下的就是如何设计这样的功能来满足你的需要,甚至使用模板。

 1 template<typename T>T* foo(std::size_t size)
 2         return new T[size] ;
 3 

【讨论】:

【参考方案5】:

作为其他答案的补充:

向量

(同意vector动态调整大小):

std::vector<int> v;
v.push_back(1);
v.push_back(1);
v.resize(v.size()+10, 5); // Greater resized
v.resize(v.size()-1);     // Lower resized
如果新大小大于旧大小,则附加元素将初始化为 5(如果不使用第二个参数,则在 int 的情况下为 0)并且旧元素保持不变。 如果新大小小于旧大小,则会被截断。

数组

旁注:(关于分配)

array 的处理方式可能会导致明显不同的结果(请参阅这个非常有趣的discussion):

// Create 500 bytes on the heap
char *pBuffer = new char[500];      // or malloc in C

// Create 500 bytes on the stack
char buffer[500];                  

【讨论】:

我确信没有将第二个参数传递给 resize 使其插入 0s(或任何 T 的默认构造函数创建的)。 谢谢,我还不熟悉矢量,所以非常感谢所有信息。

以上是关于使用 new 运算符创建用户输入大小的数组的主要内容,如果未能解决你的问题,请参考以下文章

C ++中动态大小的二维数组中的用户输入

C ++根据用户输入字符串长度创建二维数组

比较用户登录输入的数组中的用户注册信息

c++中用new给未知大小的数组分配空间怎么弄?

java中怎么直接根据用户的输入来确定数组的大小

在java中使用线性和二进制搜索的用户输入