Как использовать распределитель для std::vector?

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

я приведу простой пример, я хочу использовать вектор класса person, поэтому я должен сказать вектору шаблона: эй, храни мне несколько person, но я также должен сказать вектор, как выделить этот класс. (1) Каким будет правильный синтаксис для этого примера?

некоторый код для начала:

примечание: в конструкторе person c(2) следует использовать date*?

class date
{
public:
    int m_nMonth;
    int m_nDay; 
    int m_nYear;

    int getMonth(return m_nMonth;)
    int getDay(return m_nDay;)
    int getYear(return m_nYear;)

    void setDate(int month, int day, int year)
    {
            m_nMonth=month;
            m_nDay=day;
        m_nYear=year;
    }

    date()
    {
        setDate(0,0,0);
    }

    date(int month, int day, int year)
    {
        setDate(month,day,year);
    }

    void printDate()
    {
        printf("%d/%d/%d", m_nMonth, m_nDay, m_nYear);
    }
}

class person
{
public:
    int m_nID;
    char m_sName[128];
    char m_sSurname[128];
    date m_cBirthDay;

    void setName(const char* name)
    {
        strncpy(m_sName, name, 127);
        m_sName[127]= '\0';
    }

    void setSurname(const char* surname)
    {
        strncpy(m_sSurname, surname, 127);
        m_sName[127]= '\0';
    }

    void setBirthDay(date* bday);
    {
        m_cBirthDay.date(bday.getMonth(), bday.getDay(), bday.getYear)
    }

    person(int id, const char* name, const char* surname, date bday)/*should it be date* bday? why?*/
    {
        m_nID=id;
        setName(name);
        setSurname(surname);
        setBirthDay(bday);
    }

}

я полагаю, вам нужно объявить функцию внутри класса person, называемую распределителем, то есть то, что передается в качестве второго аргумента при вызове, (3) как будет определена эта функция распределения?:

vector <person*, /*some allocator call*/> ImAVector;

затем (4) как я могу нажать что-то в векторе, (5) будет ли это работать?:

person* someperson;
someperson.person(/*arguments*/);
ImAVector.push_back(someperson);

(6) как я могу получить указатель на конкретный экземпляр? (7) могу ли я использовать итератор, чтобы сделать что-то подобное?:

//(6)
person* = ImAVector[someIterator];
//and then (7)
ImAVector[someIterator].setName(someConstCharPointer);
string* something = person.getName();

кроме того, (8) имеет ли распределитель какое-либо отношение к конструктору? (9) его обычная процедура для заполнения полей вашего класса сразу после выделения экземпляра класса? (10) может ли распределитель вызвать конструктор?

И последние вопросы: (11) что такое поле ссылки, поле указателя и их константные аналоги?

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

Я ценю любые ответы :)


person 1.auxl2.1laux.2    schedule 31.10.2013    source источник
comment
См., например. этот ответ для примера распределителя. В большинстве случаев вам не нужен какой-либо распределитель.   -  person Basile Starynkevitch    schedule 31.10.2013
comment
Зачем вам пользовательский распределитель? Просто сделайте, например. std::vector<person*> persons; persons.push_back(new person(...)); Будет работать и без указателей: std::vector<person> persons; persons.push_back(person(...));   -  person Some programmer dude    schedule 31.10.2013
comment
И вы обычно хотите использовать какой-нибудь интеллектуальный указатель в векторе, например. std::vector<std::unique_ptr<person>>. Если возможно, используйте компилятор C++11.   -  person Basile Starynkevitch    schedule 31.10.2013
comment
спасибо за быстрый ответ, я не понимаю часть умного указателя, для чего он будет использоваться?   -  person 1.auxl2.1laux.2    schedule 31.10.2013
comment
Пожалуйста, найдите несколько часов или дней, чтобы прочитать хорошую книгу по программированию на C++11. У нас не так много времени, чтобы учить вас всему этому. См. также cplusplus.com и cppreference.com   -  person Basile Starynkevitch    schedule 31.10.2013
comment
@ 1.auxl2.1laux.2: интеллектуальные указатели используются для обеспечения правильного удаления динамически созданных объектов; Без них очень сложно избежать утечек памяти и других проблем. В вашей книге по C++ они должны быть подробно описаны; в противном случае см. (например) stackoverflow.com/questions/106508.   -  person Mike Seymour    schedule 31.10.2013
comment
Извините, я знаю, что прошу о многом, я пытался найти бесплатную книгу по С++, но, похоже, ее нет, и в стране, в которой я живу, я не могу заказывать книги из других мест, есть ли бесплатная книга с хорошие примеры вместо сбивающих с толку коротких определений cppreference.com   -  person 1.auxl2.1laux.2    schedule 31.10.2013
comment
Вы можете поискать в Интернете слишком короткие определения (например, посмотреть в Википедии и в Викикниге по C++< /а> ...)   -  person Basile Starynkevitch    schedule 31.10.2013


Ответы (2)


Каким будет правильный синтаксис для этого примера?

Если у вас нет веских причин для хранения указателей, не делайте этого. Затем вы просто объявляете

std::vector<person> people;

// In C++11, you can create people in place
people.emplace_back(id, name, surname, birthday);

// Historically, you had to create a person and copy it in
people.push_back(person(id, name, surname, birthday));

и все распределение управляется для вас.

Причины, по которым нужны указатели, включают:

  • вектор не должен управлять объектами. В этом случае вам не нужно указывать вектору, как их распределять.
  • возможно, person является базовым классом, и вы хотите хранить различные подтипы.

В этом случае я не думаю, что вам может помочь распределитель; вместо этого вы можете хранить интеллектуальные указатели для автоматического удаления объектов при удалении указателя из контейнера:

std::vector<std::unique_ptr<person>> people;
people.push_back(std::unique_ptr<person>(new person(id, name, surname, birthday)));

Альтернативой является жонглирование необработанными указателями и попытка удалить объекты в нужное время; но жизнь слишком коротка для этой чепухи.

(2) должен ли я использовать date*?

Нет. Для большого или сложного класса может быть полезно передать ссылку const, const date&; но этот класс достаточно прост, чтобы передавать его по значению. Передача указателя была бы странной, за исключением таких языков, как C, где это единственный способ передачи по ссылке.

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

people[index] дает ссылку (а не указатель) на человека с этим индексом. Если по какой-то причине вам действительно нужен указатель, используйте & для получения адреса:

person & ref = people[index];
person * ptr = &ref;

Могу ли я использовать итератор, чтобы сделать что-то подобное?

Нет, [] используется для доступа по индексу массива, а не для разыменования итератора. Если у вас есть итератор it, то *it дает вам ссылку на объект.

имеет ли распределитель какое-либо отношение к конструктору?

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

его обычная процедура для заполнения полей вашего класса сразу после выделения экземпляра класса

Обычно все члены данных инициализируются в конструкторе, да.

person Mike Seymour    schedule 31.10.2013
comment
о (2), конечно! так все гораздо понятнее, исходя из c, c++ может быть немного жестким, но это гораздо лучший способ - person 1.auxl2.1laux.2; 31.10.2013

Вам не нужно указывать ничего, кроме типа.

vector<person> people;
people.emplace_back(/* constructor arguments for a person */);  // constructs the person in place instead of copying into the vector.

person p;
p.stuff();
vector.push_back(p);  // copies p into the vector

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

person Charlie    schedule 31.10.2013
comment
people.emplace_back(аргументы конструктора); что бы это сделало? - person 1.auxl2.1laux.2; 31.10.2013
comment
@ 1.auxl2.1laux.2 он строит объект на месте, а не строит его, а затем копирует в вектор (как сказано в комментарии) - person Charlie; 31.10.2013