2

I thought I could do the following:

#include <iostream>

using namespace std;

class cl
{
  public:
    double* Arr;
    cl(int);
};

cl::cl(int i)
{
    Arr=new double[i];
    Arr[0]=11;
};

int main()
{
    cl* BB;
    BB=new cl(3)[3];      /* I want to initialize a class member Arr for each element of the class cl array BB when I initialize this array by means of constructor. What should I do? */
    cout << cl[1].Arr[0] << endl;                                                                                                   

    return 0;
}

but obviously something is wrong with the line where I noted. The compiler wouldn't compile.

cbear1985
  • 155
  • 2
  • 11

4 Answers4

3

In C++11 you can use brace initializer:

cl* BB = new cl[3] {1, 2, 3};

or more verbose, so it's clear that the numbers are passed as arguments to constructors of different objects:

cl* BB = new cl[3] {{1}, {2}, {3}}; 

Though as you are allocating memory dynamically anyway, it's better to use std::vector, also it's more convenient if you want to initialize large number of objects with the same parameters:

std::vector<cl> BB(300, 3);

However, std::vector initialization won't compile if cl doesn't have a copy constructor. In that case you can use emplace_back():

vector<cl> BB;
BB.reserve(300);
for(int i = 0; i < 300; ++i)
    BB.emplace_back(3);

This in turn can be wrapped into a template back_emplacer_iterator to use with std::fill_n

Community
  • 1
  • 1
Anton Savin
  • 40,838
  • 8
  • 54
  • 90
3

There are several approaches:

  • C++11 initializer list

    cl* BB = new cl[3] {42, 42, 42};
    
  • STL-vector (recommended)

    std::vector<cl> BB( 3, cl( 42 ) );
    

As pre-C++11 there are also other more involved solutions relying on placement new operator although I'd not recommend this.

Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246
1

The format of a new-expression is a type, followed by an initializer. If you want to allocate an array of 3 cl objects then the type is cl[3]. You can't say cl(3)[n] because cl(3) is not a type.

In C++03 the only valid initializer for a dynamically-allocated array is () which value-initializes each element, but you can't do that as your type doesn't have a default constructor.

In C++11 you can use an initializer-list to pass arguments to each array element:

cl* ptr = new cl[3]{ 3, 3, 3};
Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
0

Each element in the array will be initialized by the default constructor (no argument constructor). After that you may call any function that does the desired task. Corrected program example:

class cl
{
  public:
    double* Arr;
    cl(int i = 0);
    ~cl();
    void allocArr(int i=0);
};

cl::cl(int i)
{
    allocArr(i);
}

void cl::allocArr(int i)
{
    if (i <= 0) {
        Arr = (double *) NULL;
    }
    else {
        Arr=new double[i];
        Arr[0]=11;
    }
};

cl::~cl() {
    if (Arr)
      delete [] Arr;
}

int main()
{
    cl* BB;
    BB=new cl[3]; // default constructor 
    for (int i = 0; i < 3; i++) {
        BB[i].allocArr(3);
    }

    cout << BB[1].Arr[0] << endl;                                                                                                   

    return 0;
}
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
  • Yuck. `allocArr` leaks memory if called twice. You do not need to check a pointer is non-null before deleting it. – Jonathan Wakely Sep 19 '14 at 11:53
  • Also, it is valid to allocate 0 items, you just can't index the pointer you get for it. And as for the problem of the number being negative, a preferable solution is to replace all of the `int`s that deal with numbers that must be positive with `unsigned int`s. – rsethc Sep 19 '14 at 11:59
  • I just gave the idea of what can be done, robustness has to be checked by the original requester, if the idea helped that's fine, what's the point of downvoting in honest help – Dr. Debasish Jana Sep 19 '14 at 12:11
  • OK, but there is no way doing this by argument constructor? – cbear1985 Sep 19 '14 at 13:19