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

时间:2013-06-13 01:44:39

标签: c++ arrays dynamic-allocation

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

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

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

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

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

(PS:嗨,我是新来的,也是C ++的新手)

5 个答案:

答案 0 :(得分:6)

  

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

是的,这完全有效。请注意,您需要使用operator arr显式删除delete[]指向的内存。使用std::vector<int>会更好,它将为您执行内存管理。

您可能会误认为C++中不允许使用可变长度数组(VLA):

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

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

  

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

不,你不能扩展它。您可以分配更大的数组,复制元素并删除前一个元素。同样,如果您使用的是std::vector<int>,则会自动完成。

  

Ques3)同样,如果这个表达式是标准的,那么它是否可能   在函数中使用它 - 例如。使用函数来创建这样的   阵列? (如果是这样,怎么样?)

是的,当然:

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); 

答案 1 :(得分:3)

  

我已经研究过,数组大小必须在声明/编译器必须知道它的值时保持不变。

嗯,这是真的,但仅适用于静态自动数组。您正在堆上分配动态数组,这是不同的。

静态数组

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

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];
}

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

答案 2 :(得分:0)

作为其他答案的补充:

<强>载体

(同意动态调整大小的矢量):

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];                  

答案 3 :(得分:0)

问题1 - 运算符'new'用于进行动态分配,我的意思是,当你以前不知道数组的大小是什么时,那么,没有问题,你可以做到!我认为你的教授们对C sintax感到困惑,因为新的既不存在也不允许做类似的事情:int p [n];例如。

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

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

int* createarray(int size)
{
   return new int[size]; 
}


int main()
{
    int *p = createarray(10);
}

答案 4 :(得分:0)

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 [],deallocation函数的名称是   operator delete []。
                  - 5.3.4.8,N3242

     

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

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

部分否,或不推荐。
当分配函数返回null以外的值时,它必须是指向存储块的指针 其中保留了对象的空间。大多数分配发生在堆中,并且可能没有更多连续内存,这对于数组很重要。
如果您必须执行此操作并进行内存轮询,请使用placement new运算符,您可以部分执行此操作,但您现在所做的是分配器的设计者所做的事情,并且存在破坏内部存储器存储的风险。

问题3:使用函数创建这样的数组? (如果是这样,怎么样?)

  

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 }