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:


#ifndef BOARD_H
#define BOARD_H

#include "Square.h"

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

Square **squares;
const int width;
const int height;



#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.


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