C ++: конструктор / инициализатор для массива? - PullRequest
7 голосов
/ 07 марта 2011

Я знаком с конструкторами и инициализаторами 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 ]

5 голосов
/ 07 марта 2011

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

То есть

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]);
   }

};
2 голосов
/ 07 марта 2011

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

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);
    }

};

Надеюсь, это поможет. Привет.

1 голос
/ 07 марта 2011

В 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

Запуск в идеоне: http://ideone.com/pFcrv

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

1 голос
/ 07 марта 2011

Вы не можете (в общем) передать произвольный многомерный массив функции в 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 - к именам, начинающимся с подчеркивания, прикреплен целый набор правил, о которых вы, вероятно,хочу не думать.

РЕДАКТИРОВАТЬ: Это часть моего первоначального ответа;это неправильно:

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

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

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

0 голосов
/ 07 марта 2011

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

#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);
    }
};
0 голосов
/ 07 марта 2011

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

memset(&coeff,0,3*6*sizeof(int)) 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...