C ++ как работать с указателями на векторные указатели - PullRequest
0 голосов
/ 09 января 2019

У меня есть этот дизайн:

vector<string*>* tmp = new vector<string*>;

как мне вставить в него элементы? Я не могу понять, как я вставил в этот вектор несколько строк. Я попробовал это

std::string srt = "abc";
tmp->push_back(srt);

но компилятор ругается и синтаксис неправильный, я не знаю как это сделать

Ответы [ 4 ]

0 голосов
/ 10 января 2019

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

vector<string*>* tmp = new vector<string*>;

Вот как вы должны это сделать:

using std::vector; using std::string; using std::cout;

int main()
{
    vector<string*>* tmp = new vector<string*>;
    string srt = "abc";
    (*tmp).push_back(&srt);
    cout << *(*tmp)[0] << endl;
    delete tmp;
}

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

    tmp->push_back(&srt);
    cout << *tmp->operator[](0) << endl;

Давайте рассмотрим, что происходит с *(*tmp)[0]. (*tmp) - это вектор, на который указывает tmp. (*tmp)[0] - это содержимое первого элемента в векторе, который является указателем на строку. *(*tmp)[0] - это строка, на которую указывает первый элемент вектора.

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

Это канонический способ использования контейнеров для хранения строк.

int main()
{
    vector<string> tmp;
    string srt = "abc";
    tmp.push_back(srt);
    cout << tmp[0] << endl;
}
0 голосов
/ 09 января 2019

просто не получайте слишком много указателей (при условии, что это относительно простая программа)

vector<string> tmp;
std::string srt = "abc";
tmp.push_back(srt);

определенно, вектор указателей на строку - это катастрофа, ожидающая своего появления. И, возможно, вам не нужен указатель на вектор

0 голосов
/ 09 января 2019

Чтобы ответить на ваш вопрос:

Как работать с указателями на векторные указатели?

Давайте посмотрим на базовый пример ...

#include <iostream>
#include <string>
#include <vector>

int main() {
    // has to be initialized since it is a pointer.
    // However, this will compile but will fail at runtime.
    std::vector<std::string*>* pvWords = nullptr;

    std::string word1 = "Hello";
    std::string word2 = "World";

    // Here you need the `operator->()` from the vector
    // and since it will store pointers to strings,
    // you can just pass in the address of...
    pvWords->push_back( &word1 ); 
    pvWords->push_back( &word2 );

    for ( auto& s : *pvWords )    // here we need to dereference pvWords
        std::cout << *s << ' ';   // and here we need to dereference s
    std::cout << '\n';

    return 0;
}

- ожидаемый результат -

Hello World

Однако это скомпилируется, но завершится неудачно во время выполнения и приведет к ошибке нарушения доступа в Visual Studio. Это терпит неудачу, потому что как только указатели strings выходят из области видимости, они уничтожаются, и память, на которую vector или vector* пытается сослаться, теперь становится недействительной. Возможно, вам удастся обойти это, используя динамическую память, но даже тогда это просто делает код более сложным и сложным в управлении и может привести к еще большему количеству невидимых ошибок.

Если мы исправим вышеизложенное в следующем фрагменте кода, код будет работать:

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string*>* pvWords = new std::vector<std::string*>;

    std::string word1 = "Hello";
    std::string word2 = "World";

    pvWords->push_back( &word1 ); 
    pvWords->push_back( &word2 );

    for ( auto& s : (*pvWords) )
        std::cout << (*s) << ' ';
    std::cout << '\n';

    delete pvWords; // don't forget to cleanup dynamic memory.

    return 0;
}

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

Hello World

Однако, чтобы избежать всех этих ошибок и сложности кода, просто не используйте указатели, особенно при работе с std::string.



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

В этой ситуации нет необходимости использовать указатели. Вы не храните производные классы базового класса, где вам нужно наследование или полиморфизм.

Из-за поведения std::vector и std::string просто делаем это:

#include <iostream>
#include <string>
#include <vector>

int main() {
    std::vector<std::string> vWords;

    vWords.push_back( "Hello" );
    vWords.push_back( "World" );

    for ( auto& s : vWords )
        std::cout << s << ' ';
    std::cout << '\n';

    return 0;
}

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

-Output-

Hello World

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

0 голосов
/ 09 января 2019

Синтаксис будет tmp->push_back(&srt);

Но было бы лучше использовать vector<string>, потому что вектор позаботится о указателях для вас.

Предпочитают:

std::vector<std::string> tmp;
std::string srt{"abc"};
tmp.push_back(srt);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...