1

Here is my code:

int *arr1 = new int[size]();
int *arr2 = new int[size]();
int *arr3 = new int[size]();

I know, I know: I should be using std::unique_ptr if I need to use pointers, but I am required by an assignment to use * arrays (using "dynamic allocation" - I would use std::vector but that's not allowed either for some reason).

I know using new is bad practice, so is there a way to use a pointer array without using that keyword or having to do delete later on?

Mat
  • 188,820
  • 38
  • 367
  • 383
user473973
  • 681
  • 2
  • 12
  • 23
  • 1
    If you're told to do dynamic allocations in your assignment, you're probably expected to use `new`. Just because you should in general avoid it doesn't mean you shouldn't know how to use it properly when required. – Mat Aug 31 '13 at 15:06
  • Thanks for the response! When are the appropriate times to use `new`? – user473973 Aug 31 '13 at 15:09
  • 6
    "I know using new is bad practice". Says who? That's one of those generalizations that sounds way too general. – AShelly Aug 31 '13 at 15:10
  • @AShelly, The use cases of `new` are very rare. They're often better replaced by one of [these](http://klmr.me/slides/modern-cpp/#1). – chris Aug 31 '13 at 15:14
  • @AShelly you are correct, thank you. The reason I said that was that I saw various questions related to `new`, in that using other containers is to avoid memory leaks by forgetting to do `delete` (and other things): http://stackoverflow.com/questions/6500313/why-should-new-be-used-as-little-as-possible – user473973 Aug 31 '13 at 15:15
  • Using new/delete is bad practise when you are using it, but at the same time you can think of other solution, that doesn't require these guys. Otherwise, it's not. – Gintas_ Aug 31 '13 at 15:17
  • Hey you assignment is meant to teach you about dynamic allocation. You program is simple enough, so you don't need to worry much about memory leaks now. just remember to use delete[] to delete the array in the end. But when developing something avoid using new opeartor with simple pointer, use smart pointers – Himanshu Pandey Aug 31 '13 at 15:21
  • Why not use [unique_ptr for arrays](http://stackoverflow.com/questions/16711697/) ? – Nemo Aug 31 '13 at 15:34
  • You can follow the priciple of RAII to protect your resource or craft your own "unique_ptr".This should help you get high score in your assignment. – StereoMatching Aug 31 '13 at 17:22

6 Answers6

4

If we stick to 'classic' C++ (and not the latest bleeding edge standard), then you don't have unique_ptr or std::array, and the use of new is normal. It carries some risks of leaking storage (by failing to delete) or corrupting storage (by deleting twice), but it's your job to code things to avoid those issues.

However, there are ways of using new that are less likely to result in leaking memory, like the following. Note: This is not perfectly safe production code, just a tutorial example on the use of a class with a destructor to manage the lifetime of storage allocated with new.

class WithAnArray {
     private:
        int *storage;
     public:
        WithAnArray(unsigned size) {
           storage = new int[size];
        }
        ~WithAnArray() {
           delete[] storage;
        }
        int* getArray() {
           return storage;
        }
 }
bmargulies
  • 91,317
  • 38
  • 166
  • 290
  • The server on which they are grading has support for C++11, so it is not like we have a old compiler or something. We are also not allowed to use classes for this particular assignment for some reason. – user473973 Aug 31 '13 at 15:17
  • Yes, but your faculty might want you to be prepared to be productive in the real world. In any case, the class here gives you an idea of what needs to happen, not that you didn't know. – bmargulies Aug 31 '13 at 15:18
  • Oh yes I understand. Thank you :) – user473973 Aug 31 '13 at 15:20
  • 1
    What would happen if I did `WithAnArray a, b; a = b;`? Would this eventually crash? Cause UB? What about `WithAnArray c(x);`? – Luchian Grigore Aug 31 '13 at 15:22
  • 1
    This code violates the "rule of three". I think you need a copy constructor and assignment operator, private if nothing else. (Important enough to include even in an example template, IMO.) – Nemo Aug 31 '13 at 15:32
  • @bmargulies Just add a private copy constructor and assignment operator –  Aug 31 '13 at 16:36
2

C++11 introduced std::array :-) Is it a way to sidestep the problem? :-) :-)

The description is:

std::array is a container that encapsulates constant size arrays.

Example of use:

std::array<int, 3> a2 = {1, 2, 3};

Or you can even use std::unique_ptr, as in this example:

int size = 10; 
std::unique_ptr<int[]> fact(new int[size]);

for (int i = 0; i < size; ++i) {
    fact[i] = (i == 0) ? 1 : i * fact[i-1];
}

for (int i = 0; i < size; ++i) {
    std::cout << i << ": " << fact[i] << '\n';
}
xanatos
  • 102,557
  • 10
  • 176
  • 249
  • That would be a great idea, but according to the specifications I have to use "dynamically loaded memory using pointer arrays". I have emailed my professor about `std::vector` but have not gotten a response. I suppose `std::array` could work. The assignment I think is more about seeing "if you can code in C++" despite being an upper-division course. – user473973 Aug 31 '13 at 15:08
  • +1 But, I amn't sure how using `std::array` would be a solution if OP wants dynamic allocation depending on array size. Am I missing anything ? – Mahesh Aug 31 '13 at 15:10
  • @user473973 Then use the `unique_ptr`. It *is* compatible with dynamically allocated arrays. It has a `[]` operator just for them. – xanatos Aug 31 '13 at 15:11
  • Thanks, that would work. However, I'm required by specifications to use pointer arrays (i.e. `int *arr`). – user473973 Aug 31 '13 at 15:12
  • 1
    @user473973 a `unique_ptr` is a smart pointer. Still, if you want, you can use it to manage the deletion of the array and then `int* fact2 = fact.get()` (where `fact` is the `unique_ptr`) and then work with the "standard" pointer. In this way you are still RAII "safe", but you aren't going against the instructions you received. – xanatos Aug 31 '13 at 15:16
  • Thank you, that would be a good solution. I'll see what my professor thinks about it. – user473973 Aug 31 '13 at 15:19
1

There is nothing bad about the new keyword, it's always at the bottom of dynamic space allocation, even when you use std::vector<> and friends. std::unique_ptr and such have their issues as well. But this is not, what my answer is about.

My answer is about the cases, where you need to avoid new for performance reasons (it is a very costly operator, taking a few hundred cycles).

You can usually avoid allocating your array line by line, by simply allocating it all in one go, and building the pointer structure you need manually:

size_t fieldSize = width*height*sizeof(int);
size_t pointerArraySize = height*sizeof(int*);
char* memory = new char[fieldSize + pointerArraySize];
int** pointerArray = (int**)memory;
int* dataArray = (int*)&memory[pointerArraySize];
for(long i = height; i--; ) pointerArray[i] = &dataArray[i*width];

Ok, this is a little more hassle than doing many individual allocations, but quite a bit faster. And, as a bonus, deallocation is a one-liner:

delete[] (char*)pointerArray;
cmaster - reinstate monica
  • 33,875
  • 7
  • 50
  • 100
0

Question is if sizeis known (can be calculated) at compile time or only at runtime.

If the first situation applies, use std::array, with the latter there's no way without using new (indirectly) or some allocator surrogate passed to a STL container (e.g. std::vector).

πάντα ῥεῖ
  • 83,259
  • 13
  • 96
  • 175
  • The size is being read from the file (and so are the `int`s to be read into the arrays) so it cannot be evaluated at compile or runtime. – user473973 Aug 31 '13 at 15:11
  • _'cannot be evaluated at compile or runtime'_ this would mean you cannot evaluate it at all. I'm sure you didn't meant this! It's read from file and evaluated at runtime, so you have to use `new`. `std::vector` would do this indirectly using the `resize()` operation. But I can't tell what your prof. want's to see. – πάντα ῥεῖ Aug 31 '13 at 15:14
  • Oh yeah, sorry. It will be evaluated at runtime. I guess I'll just have to stick to pointer arrays for the moment, despite possible memory leaks. – user473973 Aug 31 '13 at 15:16
  • @user473973 As mentioned, you could still use `std::vector` (with the default allocator) and `resize()` safely, without getting any memory leaks. – πάντα ῥεῖ Aug 31 '13 at 15:20
0

You could just pass a reference to a static array sized on a huge number.

0

Anybody claiming that using new is bad practice shouldn't be allowed to develop any code, because if we expand such persuasion, then using pointers is also bad, using/developing COM objects is also bad, using heap is also bad... At the end of that demagogy would most probably be something like "using computers is bad practice, let's switch to stone age".

If you don't know how to use new/delete without creating a mess, hire somebody who does.

user1764961
  • 693
  • 6
  • 21