Как мне хранить массивы в списке STL? - PullRequest
12 голосов
/ 06 мая 2009

Используя C ++ и STL, кто-нибудь знает, как хранить целочисленные массивы как узлы в списке STL или векторе? У меня есть неизвестное количество пар чисел, которые мне нужно хранить, и, исходя из других языков, я сначала подумал о том, чтобы использовать какую-то структуру данных в виде списков или векторов ... но у меня возникают некоторые проблемы. Я на 100% уверен, что я делаю очевидную ошибку C ++ для новичка, и что тот, кто действительно знает язык, один раз посмотрит на то, что я пытаюсь сделать, и сможет уточнить меня.

Итак, вот что я попробовал. Объявление списка так работает:

stl::list<int[2]> my_list;

И тогда я легко могу создать массив из двух элементов, например:

int foo[2] = {1,2};

Это компилируется и работает просто отлично. Однако, как только я пытаюсь добавить foo в свой список, вот так:

my_list.push_back(foo);

Я получаю целый грубый набор ошибок компилятора, ни одной из которых я действительно не понимаю (мой C ++ - fu почти отсутствует):

/usr/include/c++/4.0.0/ext/new_allocator.h: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = int [2]]’:
/usr/include/c++/4.0.0/bits/stl_list.h:440:   instantiated from ‘std::_List_node<_Tp>* std::list<_Tp, _Alloc>::_M_create_node(const _Tp&) [with _Tp = int [2], _Alloc = std::allocator<int [2]>]’
/usr/include/c++/4.0.0/bits/stl_list.h:1151:   instantiated from ‘void std::list<_Tp, _Alloc>::_M_insert(std::_List_iterator<_Tp>, const _Tp&) [with _Tp = int [2], _Alloc = std::allocator<int [2]>]’
/usr/include/c++/4.0.0/bits/stl_list.h:773:   instantiated from ‘void std::list<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = int [2], _Alloc = std::allocator<int [2]>]’
test.cpp:5:   instantiated from here
/usr/include/c++/4.0.0/ext/new_allocator.h:104: error: ISO C++ forbids initialization in array new

Так, у кого-нибудь есть идеи относительно того, что я здесь делаю неправильно? Любые указатели (без каламбура) будут наиболее полезными. Разве нельзя хранить массивы в std :: list? Должен ли я использовать структуру? Я просто пропускаю * или & где-то?

Ответы [ 6 ]

24 голосов
/ 06 мая 2009

Вещи, хранящиеся в контейнере стандартной библиотеки, должны быть назначаемыми и копируемыми - массивы не являются ни тем, ни другим. Лучше всего создать список std :: vector. Кроме того, вы можете заключить массив в структуру:

struct A {
   int array[2];
};

std::list <A> alist;
9 голосов
/ 06 мая 2009

Вы не можете хранить массивы в контейнерах STL. Вы бы использовали вектор векторов или что-то подобное для общего случая. Для вашего конкретного случая я бы использовал вектор std :: pair, например: std::vector<std::pair<int, int> >. std::pair - это класс, состоящий из двух членов, first и second, любого типа, которым вы его шаблонизируете.

Редактировать: Первоначально я имел его как std::vector<std::pair<int> >, но я не был уверен, был ли он перегружен, чтобы принимать только 1 параметр в случае, когда оба типа одинаковы ... небольшое копание не обнаружило никаких доказательств этого поэтому я изменил его, чтобы явно указать, что first и second являются int с.

7 голосов
/ 06 мая 2009

Это хорошая ситуация для использования boost :: array вместо "классических" массивов в стиле C. Это должно работать:

std::list<boost::array<int,2> > my_list;
boost::array<int,2> foo={{1,2}};
my_list.push_back(foo);
5 голосов
/ 06 мая 2009

Я бы посоветовал вам использовать std :: pair для хранения значений в этом случае. Он расположен в
<utility>.

Вы можете хранить указатели на массивы в списке, но тогда вам придется иметь дело со всем управлением памятью. Использование пары намного проще, если вам нужны пары значений.

1 голос
/ 27 августа 2017

С C ++ 11 доступен ::std::array упаковщик , который можно использовать со стандартными контейнерами, такими как:

#include <array>
#include <iostream>
#include <list>
#include <cstdint>

int
main()
{
    using t_Buffer = ::std::array<::std::int32_t, 2>;
    using t_Buffers = ::std::list<t_Buffer>;
    t_Buffers buffers;
    buffers.emplace_back(t_Buffer{1, 2});
    ::std::cout << buffers.front()[0] << " " << buffers.front()[1] << ::std::endl;
    return(0);
}

Запустите этот код онлайн

1 голос
/ 27 августа 2017

Начиная с C ++ 11, мы можем сделать это со стандартом std::array:

#include <array>
#include <list>
#include <iostream>

int main () {
    std::list<std::array<int, 2>> l {{3,4},{5,6}};
    l.push_back({1,2});

    for (const auto &arr : l)
        for (const auto &v : arr)
            std::cout << v << ' ';
}

или

l.push_back({{1,2}});

и т.д.. заставить замолчать какое-то лягушатное предупреждение.

Выход:

3 4 5 6 1 2 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...