1

How to write the following code using new operator? Please explain in detail. Thanks in advance.

#include<alloc>
#define MAXROW 3
#define MAXCOL 5
using namespace std;

int main()
{
    int (*p)[MAXCOL];
    p = (int(*)[MAXCOL])malloc(MAXROW*sizeof(*p));
} 

3 Answers3

2

Quite simply, to answer the question literally:

p = new int[MAXROW][MAXCOL];

This allocates a 2D array (MAXROW by MAXCOL) on the free store and, as usual with new, returns a int(*)[MAXCOL] - the same type as decaying the 2D array. Don't forget to delete[] p;.

The last part brings up the importance of std::vector. Presumably, you know the size of the second dimension at compile-time. Therefore, a std::vector<std::array<int, MAXCOL>> would work with the added bonus of not requiring a delete[] statement, plus it knows its size (MAXROW). Please use this if at all possible.

In fact, in your example, both dimensions are known at compile-time, meaning a std::array<std::array<int, MAXCOL>, MAXROW> would also work here. That's typically preferable to dynamic allocation.

If neither dimension is known at compile-time, your best bet is usually a vector of vectors or a dedicated matrix class to increase performance when you know every inner vector is the same size.

chris
  • 60,560
  • 13
  • 143
  • 205
1

The literal question

How to write the following code using new operator?

… means something else than you think it means.

The new operator is a simple allocation function roughly directly analogous to C's malloc, except the C++ new operator is replacable by a user defined one.

You probably mean a new expression. Such an expression invokes the new operator for allocation, and then invokes a constructor for initialization, if the allocated thing is of class type. And it's type safe.

Still, for your array you'd not want that either, but simply std::vector from the standard library.


Here's an example using a std::vector of vectors to create a matrix:

#include <vector>
using namespace std;

auto main()
    -> int
{
    int const n_rows = 3;
    int const n_cols = 5;

    using Row = vector<int>;

    vector<Row> v( n_rows, Row( n_cols ) );

    // E.g. v[1] is a row, and v[1][2] is an int item in that row.
}

Even if you don't so often use matrices, it can be a good idea to wrap the general notion of a matrix, in a class. A simple way is to use a single std::vector for storage, and provide e.g. an at function or an operator() for indexing from client code. If you don't yet feel like doing this yourself, then e.g. the Boost library provides a matrix class.

Cheers and hth. - Alf
  • 142,714
  • 15
  • 209
  • 331
  • Generally, I avoid using nested vectors for N-dim array like objects. There are multiple indirections to access an element which slows things down.. – doug Jul 15 '16 at 20:07
  • @doug: I agree. That's why I recommended using a single vector as matrix storage. The simple declaration is the reason for the nested one. (In passing I find it amazing that nobody commented on the obvious typo. Fixed. :) ) – Cheers and hth. - Alf Jul 15 '16 at 20:36
  • There's a very simple way to use a single vector and still use the semantics of a 2D built in array. (http://stackoverflow.com/questions/36123452/statically-declared-2-d-array-c-as-data-member-of-a-class/36123944#36123944) – doug Jul 16 '16 at 03:39
  • @doug: Yes, that's the basic class sketched at the end of this answer. I recommend not using all uppercase identifiers. All uppercase identifiers can easily collide with macros (it's a common convention to reserve these identifiers for macros). – Cheers and hth. - Alf Jul 16 '16 at 05:10
  • @doug: More subjectively, I would not return a row pointer, because it exposes the internal implementation. E.g. it makes it difficult to let the same client code work with a view such as a transposed matrix. Instead just let `operator()` take two arguments, and return reference to item. – Cheers and hth. - Alf Jul 16 '16 at 05:18
  • Yes, I too prefer operator() but for updating older code based on [][] it models built in arrays closely. But, as you point out, it's not very easily modified for views such as transpose. I find I rarely even use new and delete these days. Modern C++ is such a pleasure. – doug Jul 16 '16 at 14:49
1

Since this is C++ I will recomend using std::array and std::unique_ptr Also when using malloc you should use free un-alloc or free the memory, if you use new you need to use delete; if you new[] you need to use delete[]

#include <cstdlib>
#include <memory>
#include <array>
#define MAXROW 3
#define MAXCOL 5
using namespace std;

int main()
{
    int (*p)[MAXCOL];
    p = (int(*)[MAXCOL])malloc(MAXROW*sizeof(*p));
    free(p); //free memory 
    array<int,MAXCOL> *p1 = new array<int,MAXCOL>[MAXROW];
    delete []p1; //use this to delete the variable
    array<array<int,MAXCOL>,MAXROW> *p2 = new array<array<int,MAXCOL>,MAXROW>;
    delete p2;  // normal delete for this one
    auto p3 = make_unique<array<array<int,MAXCOL>,MAXROW>>();
    //no delete needed for p3, it is a smart pointer.
} 
ChetS
  • 658
  • 7
  • 15