3

I need to initialize an array of objects of a parametrized constructor . How can i do it in best possible way ?

   # include<iostream>
   # include<conio.h>
   # include<stdio.h>

   using namespace std;

   class A
   {
    public:
    int a;       
    A();
    A(int x)
    {
     a=x;
    }      
   };
   int main()
   {
    A *a1,a2(1);
    a1 = (A*)malloc(sizeof(A)*10); // equivalent to A[10]. 
    for(int i=0;i<10;i++) a1[i]=a2; // Initialization is important in any program.
    for(int i=0;i<10;i++) cout<<a1[i].a; 
    getch(); 
    return 0;   
   }

This does work but is there some other way better than this ?

4
  • 1
    Why C's malloc and getch() instead of C++'s new and using iostream? Commented Feb 14, 2012 at 18:24
  • "This does work" No it doesn't; it invokes UB and only appears to work. Commented Feb 14, 2012 at 19:42
  • @ildjarn What do you mean by it invokes only UB ? I did not get what you mean to say by UB ? Commented Feb 14, 2012 at 19:45
  • @Ritesh : Undefined Behavior Commented Feb 14, 2012 at 19:45

3 Answers 3

4

The C++ way would be to use a std::vector.

std::vector<A>   a1(10, 1);

creates 10 A's initialized by 1.

Sign up to request clarification or add additional context in comments.

8 Comments

This requires A(int) to be not explicit I think ?
Probably, but it isn't in the example.
sure, wanted to be sure as I wanted to answer the very same thing but thought something was maybe amiss :)
The vector will destroy itself when it goes out of scope (at the end of main). Or you can call clear if you want to empty it earlier.
@Ritesh - You cannot just declare a destructor, you have to define it as well. But the above class doesn't need one.
|
0

This is solved using std::vector constructor taking size and base element :

A a2(1);
std::vector<A> tab(10, a2);

Comments

-1

Note that malloc does not construct objects, and so calling a1[i]=a2 is bad form. It probably seems to work fine since they are POD-ish objects, but this is not the proper way to do C++. It is undefined behavior, which is completely unpredictable. It may work ten thousand times in a row, and then erase your bank account. You should use new instead, which also constructs. Or better yet, use a vector, like the other answers suggest. Also, be sure that the default constructor initializes the data, and initialization will be less of a worry.

If you really must use malloc, the "correct way" to initialize is this:

std::uninitialized_copy(a1, a1+10, a2); //constructs and assigns

which is roughly equivalent to:

{
    int i=0;
    try {
        for(i=0; i<10; ++i)
           new(a1+i)A(a2); //constructs and initializes in the buffer
    } catch(...) { 
        try {
            for(; i>=0; --i)
               (a1+i)->~A(); //destroy if an error occured
        } catch(...) { 
            std::terminate();
        }
        throw;
    }
}

5 Comments

I wouldn't expect the A(int) constructor to throw. Or the default copy constructor.
@BoPersson: true, but when he does this again with std::string, and is surprised that his program crashes? I'll teach the generic correct (and easy!) way.
"and I'm pretty sure it's undefined behavior" It definitely is.
@ildjarn: I wasn't 100% sure, since the definition of POD has changed, and PODs are exceptions to some relevant rules.
@MooingDuck +1 For Genric Correct way :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.