Creating a user-inputted sized Array using new ope

2019-06-17 02:42发布

问题:

I have a few array-related questions. I've studied that array-size must be constant on declaration/compiler must know its value. But using the GNU GCC compiler (C++11 standard filter) and I am able to perfectly compile and run a program using a variable as array size, when declaring said array dynamically (using new)

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

Ques1) Is this considered standard? My profs are contradictory.

Ques2) If it is standard, in that case, is it possible to extend the size of the array (or any array) after creation?

Ques3) Again, if this expression is standard, then is it possible to use it within a function - eg. using a function to create such an array? (if so, how?)

(PS: Hi, I'm new here and also still a novice in C++)

回答1:

Ques1) Is this considered standard? My profs are contradictory.

Yes, this is completely valid. Note that you need to explicitly delete the memory pointed by arr using operator delete[]. It is much better to use a std::vector<int> which will perform the memory management for you.

You might be mistaken with variable length arrays(VLAs), which are not allowed in C++:

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

This is valid in C but invalid in C++(C++14 will include VLAs, although they will have some differences with C VLAs).

Ques2) If it is standard, in that case, is it possible to extend the size of the array (or any array) after creation?

No, you can't extend it. You can allocate a bigger array, copy the elements and delete the previous one. Again, this is done automatically if you're using std::vector<int>.

Ques3) Again, if this expression is standard, then is it possible to use it within a function - eg. using a function to create such an array? (if so, how?)

Yes, of course:

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

But again use 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); 


回答2:

I've studied that array-size must be constant on declaration/compiler must know its value.

Well, that's true, but only for static or automatic arrays. You are allocating a dynamic array on the heap, which is different.

Static array

An array declared at global scope must have a constant size.

int arr[5];

Automatic array

An array allocated automatically within a function must have constant size (with exception, see below).

void f() {
    int arr[5];
}

Dynamic array

A dynamic array allocated on the heap with new can have any size, constant or variable.

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

GCC extension

The exception is that GCC allows one to use a variable to declare the size of an automatic array:

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

However, this usage is not standard.



回答3:

Question 1 - operator 'new' is used to make dynamic allocation, I mean, when you don't know previously what is the size of the array, so, there is no problem, you can do it! I think your profs are confusing with C sintax, where new neither exists and is not allowed to make things like: int p[n]; for instance.

Question 2 - No, it is not possible increase the size of an array created using operator new. You have to alocate another array and copy the data. You can consider use vector in order to do it easily.

Question 3 - I don't see why to do it, but it is possible..

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


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


回答4:

Q1:Is this considered standard?

Given the definition int n = 42, new float[n][5] is well-formed (because n is the expression of a noptr-new-declarator), but new float[5][n] is ill-formed (because n is not a constant expression). --5.3.4.6,N3242

If the allocated type is an array type, the allocation function’s name is operator new[] and the deallocation function’s name is operator delete[].
--5.3.4.8,N3242

new T[5] results in a call of operator new[](sizeof(T)*5+x) Here, x and y are non-negative unspecified values representing array allocation overhead;
--5.3.4.12,N3242

Q2:If it is standard, in that case, is it possible to extend the size of the array (or any array) after creation?

Partially no, or not recommended.
when the allocation function returns a value other than null, it must be a pointer to a block of storage in which space for the object has been reserved. Mostly allocation happened in heap, and there may not have more contiguous memory left which is important for array.
If you have to do this and have a memory poll, use placement new operator you can do this partially, but what you do now is what the designer of allocator do, and have risk ruin the inner memory storage.

Q3: using a function to create such an array? (if so, how?)

Entities created by a new-expression have dynamic storage duration (3.7.4). [Note: the lifetime of such an entity is not necessarily restricted to the scope in which it is created. — end note ] --5.3.4.1,N3242

The rest of things are how to design such function to meet your need, even use template.

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


回答5:

As a complement to other answers :

Vectors

(Agreed with vector for dynamic resize) :

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
  • If the new size is greater than the old one, additional elements will be initialized to 5 (or 0 in case of int, if the second parameter is not used) and ancient elements remain unchanged.
  • If the new size is lower than the old one, it is truncated.

Arrays

Side note : (about stack and heap allocation)

The way an array is handled can lead to significantly different results (See this very interesting 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];