С++: конструктор / инициализатор для массива?

Я знаком с конструкторами и инициализаторами C++:

class Foo {
   int x;
public:
   Foo(int _x) : x(_x) {}
};

Foo foo1(37);
Foo foo2(104);

мой вопрос в том, что я должен реализовать класс, который имеет член, который является массивом 3x6. Как бы я сделал что-то подобное вышесказанному?

class Bar {
   int coeff[3][6];
public:
   // what do I do for a constructor????
};

edit: для простого массива я бы сделал следующее, Я просто не знаю, как это сделать для класса:

 static int myCoeffs[3][6] = 
 {{  1,  2,  3,  4,  5,  6}, 
  {  7,  8,  9, 10, 11, 12},
  { 13, 14, 15, 16, 17, 18}};

edit 2: по разным причинам (например, это встроенная система с ограничениями) мне не нужно использовать Boost, поэтому, если это предлагает решение, которое я не могу использовать.


обновление: я не привязан к инициализатор. Это нормально, чтобы сделать это в теле конструктора,и он не должен быть встроенным. Я просто ищу правильный способ построить экземпляр класса, которому нужен массив коэффициентов, не испортив назначение указателя или что-то еще.

6 ответов


ты не можешь. В C++03 вы не можете инициализировать массив в списке ctor-initalization. Однако вы можете сделать это в теле конструктора (технически это больше не инициализация).

что это

struct x
{
    int a[4];
    x():a({1,2,3,4}) //illegal
    {
        a[0] = 1;
        etc. 
    }
};

Edit: после редактирования вопроса вот способ сделать это

#include <algorithm>
struct x
{
   int arr[3][4];
   x(int (&arg)[3][4])
   {
      std::copy(&arg[0][0], &arg[0][0]+3*4, &arr[0][0]);
   }

};

Я не знаю, звучит ли это слишком очевидно, но почему бы просто не скопировать значения?

class Foo {
    static const int X = 3;
    static const int Y = 6;

    int mCoeff[X][Y];

    void setCoeff(int coeff[X][Y]) {
        for (int i = 0; i < X; i++) {
            for (int j = 0; j < Y; j++) {
                mCoeff[i][j] = coeff[i][j];
            }
        }
    }
public:
    Foo(int coeff[X][Y]) {
        setCoeff(coeff);
    }

};

надеюсь, что это помогает. С уважением.


В C++03, поскольку вы не можете инициализировать массив в списке инициализации, вы можете написать общий шаблон функции для заполнения массива заданным массивом, как показано в следующем примере,

template<typename T, size_t N>
void array_fill(T (&dest)[N], T (&src)[N])
{
   for ( size_t i = 0 ; i < N ; i++ )
       dest[i] = src[i];
}
struct A
{
   int a[5];
   A(int (&i)[5]) { array_fill(a, i); }
   void print() 
   {
      for ( int i = 0 ; i < 5 ; i++ ) cout << a[i] << " ";
   }
};
int main() {
        int a[5] = {1,2,3,4,5};
        A obj(a);
        obj.print();
        return 0;
}

выход:

1 2 3 4 5

запуск в ideone:http://ideone.com/pFcrv

Ну, тут уже std::copy который можно использовать также.


вы не можете (в общем) передать произвольный многомерный массив функции на C или C++, как это было бы в Java (я упоминаю Java, потому что именно там ваша история вопросов предполагает, что ваш опыт лежит).

на самом деле нет возможности поддерживать что-либо вроде инициализаторов массива для вашего класса в текущем стандарте, хотя есть некоторые планы изменить это в следующей версии, C++0x.

если вы хотите, чтобы это имело гибкость, скажем, массивов Java (где клиенты могут изменить размер указанного массива, у вас есть несколько вариантов. Первым и лучшим было бы использовать std::vector<>, который реализует динамический массив, но вы можете быть ограничены на вашей встроенной платформой. Вы также можете реализовать вещи самостоятельно в виде одномерного массива и принять динамический блок памяти. Пример:

class Foo
{
    int *theArray_;
    unsigned int rows_;
    unsigned int cols_;
public:
    Foo(int *theArray, int rows, int cols)
        : theArray_(theArray)
        , rows_(rows)
        , cols_(cols)
    { }
    void UseTheArray()
    {
        //Access array[5][6]
        theArray[5*cols+6];
    }
};

обратите внимание, что в этом случае вызываемый отвечает за передачу памяти. Также рассмотрите возможность использования std::auto_ptr выше вместо необработанный указатель, чтобы было ясно, кто несет ответственность за уничтожение блока памяти при уничтожении объекта.

Также обратите внимание, что вы не должны использовать имя _x - имена, начинающиеся с подчеркивания, имеют целую кучу правил, прикрепленных к ним, о которых вы, вероятно, хотите избежать думать.

EDIT: это фрагмент моего первоначального ответа; это неправильно:

Многомерный массив в C++ - это всего лишь один блок памяти. Можно принять многомерный массив, подобный этому, только в одном случае - когда вы заранее знаете точные размеры массива в классе. Тогда вы могли бы написать что-то вроде:

class Foo {
   int coeff[3][6];
public:
   Foo(int _x[3][6]) : coeff(_x) {}
};

обратите внимание, однако, что размер массива фиксирован и не может быть изменен клиентами вашего класса.


Если вам нужно пойти этим путем, я бы просто пошел на цикл for, повторяющий элементы двумерного массива и инициализирующий их. Или, если вы идете на скорость, что-то вроде memset сделает трюк.

memset(&coeff,0,3*6*sizeof(int)) 

вы можете сделать это так:

#include <algorithm>
class Bar 
{    
    int coeff[3][6]; 
public:    // what do I do for a constructor???? 
    Bar()
    {
        int myCoeffs[3][6] = 
        {
            {  1,  2,  3,  4,  5,  6},    
            {  7,  8,  9, 10, 11, 12},   
            { 13, 14, 15, 16, 17, 18}
        }; 
        std::swap(coeff, myCoeffs);
    }
};