Указатель на вектор указателя в C

#c #pointers #iterator

#c #указатели #итератор

Вопрос:

Я изучаю C и столкнулся с аналогичной ситуацией в своем задании. Каждая из моих попыток решить этот случай сопровождалась несколькими вопросами, поэтому я упростил его здесь.

Для этого сценария я буду использовать этот класс:

 class Story {
    string _title;

    //a simple getter
    string getTitle(){ 
        return _title;
    }
};
  

Теперь в моей основной функции у меня есть stories указатель на вектор с указателями на Story :

 vector<Story *> * stories = function();
  

Моя цель — получить доступ к _title первому Story в моем векторе (размер моего вектора всегда будет больше 0).

Для этого я попробовал несколько методов, которые, как я думал, будут работать:

 //Attempt 1 (doesn't work)
*(stories)[0]->title(); 
    //I thought `*(stories)[0]` returns the first `Story*`
    /** Error message:
     * error: ‘class std::vector<Story*>’ has no member named ‘title’
     */
//Attempt 1.5 (equivalent to Attempt 1)
*(stories).at(0)->title();

//Attempt 2 (works)
stories->at(0)->title(); 
    //Aren't `*(stories).at(0)` and `stories->at(0)` the same?
    //Since Attempt 1.5 failed, there as to be a difference..

//Attempt 3 (doesn't work)
stories->begin()->title(); 
    //I thought `stories->begin()` returns the first `Story*`
    /** Error message:
     * error: request for member ‘title’ in 
     * ‘* stories->std::vector<Story*>::begin().__gnu_cxx::__normal_iterator<Story**, std::vector<Story*> >::operator->()’, which is of pointer type ‘Story*’
     * (maybe you meant to use ‘->’ ?)
     */
  

Я понимаю, почему моя попытка 2 работает, но я не понимаю, почему 1, 1.5 и 3 этого не делают.

На всякий случай я компилирую, используя эти параметры:

 --std=c  11 -O0 -ggdb -Wall -Wextra
  

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

1. 🤔 #3 выглядит как опечатка.

2. *(stories).at(0) это не то же stories->at(0) самое, что . (*stories).at(0) является. Обратите * внимание, что находится внутри () , поэтому значение другое.

3. Представьте, если stories->begin() бы вы вернули первый Story* , как бы вы получили второй? Конечно, он должен возвращать что-то, что вы можете увеличить, чтобы получить следующий Story* , и это не будет значением первого Story* , не так ли?

4. Я только что попробовал, как @Peter, для попыток 1 и 1.5. Я никогда не замечал * , чтобы add был внутри. На самом деле была опечатка, поскольку @TrebledJ «указал» на попытку 3 и пояснительную справку @DavidSchwat для итератора. Спасибо вам всем.

5. C преуспевает в семантике значений. Неважно, как это сделать, пожалуйста, не делайте этого. vector может содержать историю напрямую.

Ответ №1:

begin возвращает итератор (указывающий на начало вектора), и итератор должен быть разыменован, чтобы получить элемент, на который он указывает.

С begin()-> помощью (или (*stories->begin()) ) вы разыменовываете этот итератор и получаете Story * , но Story * не имеет члена title . Так что это должно быть (*stories->begin())->title()

Или используйте front, поскольку он возвращает ссылку на первый элемент.

Ответ №2:

В случае вашей попытки 3,

stories->begin() вернет итератор, чтобы напечатать значение, сохраненное в позиции, указанной итератором, попробуйте что-то вроде этого

 *(stories->begin())
  

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

1. Действительно, все работает с этим: (*stories->begin())->title();