как получить указатель на заголовок std :: set в c ++ - PullRequest
0 голосов
/ 30 декабря 2018

как я могу получить указатель на первый элемент в наборе

   int main()
   {
    std::vector<int> v ;
    v.insert(v.end() , 1);
    v.insert(v.end() , 2);
    v.insert(v.end() , 5);
    v.insert(v.end() , 4);

    std::set<int> s ;

    s.insert(s.end() , 754);
    s.insert(s.end() , 5);
    s.insert(s.end() , 3);
    s.insert(s.end() , 4);

    std::list<int> l ;

    l.insert(l.end() , 45);
    l.insert(l.end() , 5);
    l.insert(l.end() , 3);
    l.insert(l.end() , 4);

    int *p = (int*)(&*l.begin());  <<<<<<-------- ( here )
    cout << *p++ <<endl;
    cout << *p++ <<endl;
    cout << *p++ <<endl;
    cout << *p <<endl;

он работает с векторами, но он дает мне ненужное значение с множеством и перечислить любую идею ??

Ответы [ 3 ]

0 голосов
/ 30 декабря 2018

@ rsjaffe прав, вы должны использовать iterator.

Но, кроме того, вы используете объекты.

Эти объекты имеют некоторую ответственность, а именно хранят вещи с некоторыми гарантиями.

Неопределенно:

  • быстрый доступ для чтения / записи к элементам для std::vector
  • автоматической сортировки и сохранение одного при вставке для std::set (и относительно быстрая вставкаи получение ...)
  • быстрая вставка / удаление для std::list

Цель этих классов состоит в том, чтобы эти понятия работали и в то же время скрывали свои внутренниеработает.

Аналогично, у вас есть хороший пульт с красивыми кнопками, но вы не можете знать, как они работают, и производитель не дает никаких гарантий, что он будет работать так же со временем.Вы просто знаете, что это работает (или вы можете проверить это, если хотите).

Точно так же, Iterators это вещи , которые инкапсулируют трансверсальные коллекции .

Нет такой вещи, как указатель на голову в std::set, потому что элементы не сохраняются таким образом.

В этой перспективе приведениеstd::vector::iterator к указателю работает случайно , и вопрос не имеет значения.

0 голосов
/ 30 декабря 2018

Поскольку макет памяти вектора представляет собой смежные области памяти типа содержащихся элементов, поэтому созданный указатель является обычным указателем C.

Для множества и списка содержащиеся элементы являются частью структуры.Для списка это может выглядеть так:

struct list {
  int value;
  struct list *next;
}

или

struct list {
  struct list *next;
  int value;
}

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

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

0 голосов
/ 30 декабря 2018

Будьте очень осторожны с арифметикой указателей и контейнерами.std :: vector использует непрерывную память, а указатели будут работать как положено.Другие контейнеры могут не хранить информацию в смежной памяти, и приращению указателя может не удаться перебирать контейнер.

Вместо этого используйте итераторы.например:

std::set<int> s;
//add stuff to the set
auto setit = s.begin(); //setit is an iterator for s
cout << *setit++ << endl;
//etc.

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

Например, прочитайте документацию для std :: set .Он описывает, какие типы итераторов могут быть использованы.В документации по каждому из модификаторов также указывается, являются ли итераторы недействительными.Например, если вы используете insert в наборе, итераторы не будут аннулированы.

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