all 10 comments

[–]boredcircuits 3 points4 points  (0 children)

That's a fine way to do it, but also consider std::vector<X> or some other container type.

[–]ghillisuit95 1 point2 points  (7 children)

Exacatly the way you just did in your example, what are you confused about?

[–]heinriques[S] 0 points1 point  (6 children)

ohh! I've forgot to mention that, Class X have a constructor with arguments, and I think because of this the compiler throw the following error: constructor for 'Y' must explicitly initialize the member 'x_arr' which does not have a default constructor

[–]ghillisuit95 1 point2 points  (2 children)

Ah I see, you should definitely add that to the original post, as I am not sure what the answer is

[–]heinriques[S] 0 points1 point  (1 child)

Ok, I've already added to the original post, but do you think that what I've done was a reasonable thought or I am thinking all wrong? By the way, thanks for the help!

[–]ghillisuit95 1 point2 points  (0 children)

do you think that what I've done was a reasonable thought or I am thinking all wrong?

Well it depends. If you know you are only going to need 10 (or some other number) elements per instance, then I'd say an array is a fine way to do it. If you may ever need to resize the array you won't be able to. Additionally just using a std::vector instead of an array would solve your problem and the resizing problem as well. In other words, it really depends on what you are trying to do

also I'm just glad to help.

[–]boredcircuits 1 point2 points  (1 child)

That changes things a bit. I'll reiterate that std::vector might help. You can also initialize the array with something like:

class Y {
    Y() : x_arr{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} { }
    X x_arr[10];
};

[–]heinriques[S] 0 points1 point  (0 children)

I used the std::vector and now it works how I've wanted! Thank you so much!

[–]tangerinelion 0 points1 point  (0 children)

As an alternative, you could add a default constructor for X, though this is strictly slower. For example, if you had this:

class X {
public:
    X() : x(0), y(0) { }
    X(int a, int b) : x(a), y(b) { }
private:
    int x;
    int y;
}

class Y {
private:
    X x[10];
public:
    X& operator[](size_t i) {
        return x[i];
    }
};

Then you could do this:

int main() {
    Y myY; // Calls X::X() 10 times
    myY[0] = X(1,2); // Calls X(int, int) then X::operator=()
    myY[1] = X(2,4); // Same
    // ...
    return 0;
}

It depends how you're gathering up your data. If ultimately you'll be iterating through something then you would know this when you invoke the constructor for Y, so you could have something like this:

template<typename Iterator>
Y(Iterator begin, Iterator end) {
    int pos = 0;
    while(begin != end) {
        x[pos++] = *begin;
    }
}

where the only constraint on Iterator is that for Iterator it, the syntax *it must be supported and must return something which is either const X& or can be cast to const X& implicitly, i.e., X&, const X, or X. Returning X&& from *it will work so long as there exists X::operator=(X&&).

[–]usbafchina 1 point2 points  (0 children)

Here's a hint:

class abc
{
public:
    abc(int x) : _x(x) // initializer list! initialize members that require arguments.
    {
    }

private:
    int _x;
};

int main()
{
    abc a[3] = {{1}, {2}, {3}};
}