Чтобы ответить на ваш вопрос:
Как работать с указателями на векторные указатели?
Давайте посмотрим на базовый пример ...
#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
Эта версия кода намного проще для чтения, более понятна для работы и отладки, проще для других и будет делать именно то, что вы ожидаете от нее. Это решение очень простое, быстрое и эффективное без лишних хлопот.