wKavey wKavey -4 years ago 107
C++ Question

Initializing a two-dimensional object array in c++

I know this has been asked before (or some similar variations) however I cannot get it to work.

I am trying to create a board game that is composed of a board filled with squares. I am trying to model my board as a 2d array of Square objects. The board can be created with any width or height, and those parameters are passed in through the constructor. Here is the code I am working with:

Board.h


#ifndef BOARD_H
#define BOARD_H

#include "Square.h"

class Board{
public:
Board(int w, int h);

private:
Square **squares;
const int width;
const int height;
};

#endif


Board.cpp


#include "Board.h"

Board::Board(int w, int h):width(w), height(h) {
squares = new Square*[width];

for (int i = 0; i < width; i++) {
squares[i] = new Square[height];
}
}


However, when I try to compile this I get an error which seems to indicate the
squares[i] = new Square[height]
is trying to call the default constructor for the Square object (which I do not want to exist nor call in this case).

Board.cpp: In constructor ‘Board::Board(int, int)’:
Board.cpp:7:33: error: no matching function for call to ‘Square::Square()’
squares[i] = new Square[height];


Any ideas? Is this possible within C++?

Answer Source

Your code is equivalent to this:

struct Foo
{
    Foo(int){} // no default constructor
    // Foo() = default; /* uncomment this and it will work */
};

int main()
{
    Foo* pFoo = new Foo[10]; // need a default ctor
    delete[] pFoo;
}   

The problem is that on the rhs of Foo* pFoo = new Foo[10];, you are allocating the memory as well as creating 10 Foo objects. The compiler doesn't know how to do the latter (creating the objects), as you don't provide a default constructor. To make the above code work as is, you need to specify all arguments for the non-default ctor of each object, like:

Foo* pFoo = new Foo[10]{1,2,3,4,5,6,7,8,9,0}; // this will work

The better alternative is to use std::vector instead. If you wonder why the latter works without the need for objects that don't have a default constructor, it is because it uses the placement new, and initializes the elements on demand.

Here you can see how to do it with placement new.

EDIT

The code

Foo* pFoo = new Foo[10]{1,2,3,4,5,6,7,8,9,0}; 

compiles in gcc, but clang fails to compile it (with -std=c++11 flag). Follow up question here.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download