Страницы

Поиск по вопросам

суббота, 8 февраля 2020 г.

Конструктор <vector>

#cpp #классы #перегрузка_операторов #конструктор #вектор


Хочу написать конструктор класса, который в качестве параметра принимает статический
массив (указатель на 1 элемент) и инициализирует вектор внутри класса этим массивом:

class A
{ 
  public:
    explicit A(int x[]):v(x,x+sizeof(x)/sizeof(*x)) {} // или (int* x)
  private:
    vector v;
};


Не работает... В чём проблема?
    


Ответы

Ответ 1



Параметр вашего конструктора имеет тип int *. Поэтому выражение sizeof(x)/sizeof(*x) эквивалентно выражению sizeof( int * )/sizeof( int ) И может равняться либо 2, если размер указателя равен, например, 8 байтам, а размер объекта типа int равен 4 байтам, либо 1, если данные размеры совпадают. Лучше объявить два перегруженных конструктора. Первый конструктор может быть определен как A( const int *first, const int *last ) : v( first, last ) {} а второй конструктор может быть определен либо как A( const int *first, size_t n ) : v( first, first + n ) {} либо использовать делегирующий конструктор A( const int *first, size_t n ) : A( first, first + n ) {} Также вы можете объявить шаблонный конструктор, как, например, template A( const int ( &a )[N] ) : v( a, a + N ) {} Вот демонстрационная программа, в которой показаны все три способа вызова конструкторов класса #include #include struct A { A( const int *first, const int *last ) : v( first, last ) {} A( const int *first, size_t n ) : v( first, first + n ) {} template explicit A( const int ( &a )[N] ) : v( a, a + N ) {} std::vector v; }; int main() { int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; A a1( a, a + sizeof( a ) / sizeof( *a ) ); for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl; A a2( a, sizeof( a ) / sizeof( *a ) ); for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl; A a3( a ); for ( int x : a1.v ) std::cout << x << ' '; std::cout << std::endl; } Ее вывод на консоль 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9

Ответ 2



В параметрах функции, в отличие от объявлений массива, int x[] вырождается в int* x, т.е. ничем не отличается от обычного указателя. (Параметры int x[5] или int x[6] также вырождаются int* x). Поэтому надо использовать шаблон и ссылку на массив. class A { public: template explicit A(int (&x)[N]) : v(x, x + N) {} private: vector v; }; Ссылка int (&x)[N] не теряет количество элементов в массиве.

Комментариев нет:

Отправить комментарий