3

I need to create an array of objects with non default constructor. What language feature should be applied to achieve this?

This line of code doesn't let me do that.

Object objects[10]{("foo", "bar")};

8 Answers8

2

Unless you want to specify all individual objects in the initializer list, it's not really possible with plain simple arrays.

However with a std::vector it is dead simple, because there is a constructor overload that takes the size of the vector and the object to initialize all elements to. So you can do something like

std::vector<Object> objects(10, Object("foo", "bar"));

The above will create a vector with ten elements, all elements initialized to copies of Object("foo", "bar").

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • 1
    Any explanations why this doesn't work in terms of low level programming? –  Jan 13 '17 at 12:39
  • @Tracy What do you mean by "low level programming"? That you want to make it work with plain arrays? Why? Either you adapt to use the facilities that are available to you in the language, or you adapt to work around what you might see like deficiencies (like explicitly initializing each and every element in the array). Either way, you can't hammer the language into the form and shape you want, you have to adapt. Or change language to one that might better fit your needs (which is just another kind of adaption from your side). – Some programmer dude Jan 13 '17 at 12:45
  • Why? I want to understand all of that stuff as deed as i can. I like low level programming. –  Jan 13 '17 at 14:26
  • @Tracy Traditionally "low level programming" means writing on bare-bones hardware, like low-level device drivers or for small embedded systems. Using vectors or arrays is really irrelevant IMO. Also, using what you call "low level programming" (supposedly using plain arrays and pointers) usually makes your program harder ro maintain and more prone to errors. While it's good to know the principles and how to use arrays and pointers, your life as a C++ programmer will be *so* much easier if you use the full features of the standard library. – Some programmer dude Jan 13 '17 at 14:32
  • I think for this solution to work, you also need the copy constructor for the element type to be stored in the vector. For certain objects, copy constructor is intentionally deleted. So you may have to constructor each object in place with the_ vector.emplace(the_vector.end(), args_for_constructor...) – Kemin Zhou Dec 24 '20 at 20:27
1

You can use vector or array of pointers on your object.

Object* arr[6];
for (int i = 0; i < 6; i++)
{
     arr[i] = new Object("angry dog", 6);
}
viceriel
  • 835
  • 12
  • 18
0

Use = and pass your values for non-default ctor in initializer list. This way you should define every value in the array, though.

Example

int main()
{
    struct A {
        int _v;

        A(int v) : _v(v) {}
    };

    A my_a[3] = {0, 1, 2};

    for (auto i : my_a)
      std::cout << i._v << ", ";
    std::cout << "\n";

}
pergy
  • 5,285
  • 1
  • 22
  • 36
0

Short answer is there is no way to do that with raw array. An alternative way would be to use std::vector which offers that possibility.

webNeat
  • 2,768
  • 1
  • 20
  • 22
0

Something like this?

#include <array>
#include <iostream>

struct foo {
    int a, b;
};

int main()
{
  std::array<foo, 4>  v= {{ {1, 2}, {2, 3}, {3, 4}, {4, 5} }};
  for (auto f : v) {
      std::cout << f.a << ' ' << f.b << std::endl;
  }
}
Nim
  • 33,299
  • 2
  • 62
  • 101
0

Using Double pointer (pointer to pointer concept): A pointer to a pointer is a form of multiple indirections, or a chain of pointers. Normally, a pointer contains the address of a variable. When we define a pointer to a pointer, the first pointer contains the address of the second pointer, which points to the location that contains the actual value as shown below. Here we can assign a number of blocks to be allocated and thus for every index we have to call parameterised constructor using the new keyword to initialise

#include <iostream> 
#include <string>
#define N 5 
  
using namespace std; 
  
class Test { 
    // private variables 
    string x, y; 
  
public: 
    // parameterised constructor 
    Test(string x, string y) 
    { 
        this->x = x; 
        this->y = y; 
    } 
  
    // function to print 
    void print() 
    { 
        cout << x << " " << y << endl; 
    } 
}; 
  
int main() 
{ 
    // allocating array using 
    // pointer to pointer concept 
    Test** arr = new Test*[N]; 
  
    // calling constructor for each index 
    // of array using new keyword 
    for (int i = 0; i < N; i++) { 
        arr[i] = new Test(to_string(i), to_string(i + 1)); 
    } 
  
    // printing contents of array 
    for (int i = 0; i < N; i++) { 
        arr[i]->print(); 
    } 
  
    return 0; 
} 
Artem
  • 79
  • 9
0

ARRAY in C++ can means different things. array<T, int> for fixed sized array added in C++11, raw array of objects T[] (same as T*), or vector.

  1. array<T, 3> = { } you can explicitly initialize each object, such as string("ad") inside the curly bracket.
  2. T* or T[] this you cannot do, only way is to initialize with default constructor.
  3. T** or T*[], you can initialize wit any parameterized constructor of T
  4. vector You can use emplace(v.end(), args...) [optionally in a loop] to initialize to the same or variable parameters. This may be more efficient than 3 because in 3 objects may be dispersed in different memory locations.

The above list may not be complete, and there might be mistakes. The intention is to start this thread of thinking and welcome others to correct and improve.

Kemin Zhou
  • 6,264
  • 2
  • 48
  • 56
0

Years later, I had the same problem. And I'm using this simple construct:

class test{
  const char *x;
public:
  test(const char *a): x(a) {} //no default constructor
};

//workaround for static initializer
template <typename T> class obj_init: public T{
public:
  obj_init(): T("foo") {} //parameters
};

//static array
obj_init<test> list[10];

Regards, Gabriel

Gabriel C.
  • 31
  • 1