8

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

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

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

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

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

(PS:嗨,我是新来的,而且还是 C++ 的新手)

4

5 回答 5

7

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

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

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

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

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

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

不,你不能延长它。您可以分配一个更大的数组,复制元素并删除前一个。同样,如果您使用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); 
于 2013-06-13T01:51:11.690 回答
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];
}

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

于 2013-06-13T01:57:19.230 回答
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)并且古老的元素保持不变。
  • 如果新大小小于旧大小,则将其截断。

数组

旁注:(关于堆栈分配)

处理anarray的方式会导致明显不同的结果(参见这个非常有趣的讨论):

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

// Create 500 bytes on the stack
char buffer[500];                  
于 2013-06-13T02:02:59.793 回答
0

问题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);
}
于 2013-06-13T02:06:27.083 回答
0

Q1:这算是标准吗?

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

如果分配的类型是数组类型,则分配函数的名称是 operator new[],而释放函数的名称是 operator delete[]。
-- 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 }
于 2013-06-13T10:07:23.870 回答