使用 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<int>
,它会为您执行内存管理。
你可能会误认为可变长度数组(VLA),这是C++
中不允许的:
// same num as the one in your example
int arr[num]; // ERROR
这在C
中有效,但在C++
中无效(C++14 将包含 VLA,尽管它们与 C
VLA 会有一些差异)。
问题2)如果是标准的,在这种情况下,是否可以扩展 创建后数组(或任何数组)的大小?
不,您不能扩展它。您可以分配一个更大的数组,复制元素并删除前一个。同样,如果您使用 std::vector<int>
,这将自动完成。
问题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 new
将 size_t
作为其参数,因此最好使用此类型而不是 int
以避免错误/警告。【参考方案2】:
我研究过数组大小在声明时必须是常量/编译器必须知道它的值。
嗯,没错,但仅适用于 static 或 automatic 数组。您正在堆上分配一个 动态 数组,这是不同的。
静态数组
在全局范围内声明的数组必须具有恒定大小。
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
使其插入 0
s(或任何 T
的默认构造函数创建的)。
谢谢,我还不熟悉矢量,所以非常感谢所有信息。以上是关于使用 new 运算符创建用户输入大小的数组的主要内容,如果未能解决你的问题,请参考以下文章