Можно ли создать вектор указателей?
-
03-07-2019 - |
Вопрос
Просто интересно, из-за проблемы, с которой я столкнулся, можно ли создать вектор указателей?И если да, то как?В частности, относительно использования итераторов и .begin() с ним, т.е.:Как бы я превратил этот вектор в вектор указателей:
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c>cvect
cvect.push_back(cobj);
vector<c>::iterator citer
for(citer=cvect.begin();citer<cvect.end();citer++)
{
citer->func();
}
Решение 2
vector <c> cvect
не является вектором указателей. Это вектор объектов типа c. Вы хотите vector <c*> cvect
. и вы, вероятно, хотите:
cvect.push_back( new c );
А затем, учитывая итератор, вы хотите что-то вроде:
(*it)->func();
Конечно, вполне вероятно, что вам вообще не нужен вектор указателей ...
Другие советы
Конечно.
vector<c*> cvect;
cvect.push_back(new sc);
vector<c*>::iterator citer;
for(citer=cvect.begin(); citer != cvect.end(); citer++) {
(*citer)->func();
}
Что следует иметь в виду:
Вам нужно будет выполнить очистку после себя, если вы используете динамически выделяемую память, как я это сделал в своем примере.
например.:
for(...) { delete *i; }
Это можно упростить, используя вектор shared_ptr
с (как boost::shared_ptr
).Не пытайтесь использовать std::auto_ptr
для этого он не будет работать (даже не скомпилируется).
Еще одна вещь, о которой следует помнить: вам следует избегать использования <
чтобы сравнивать итераторы в вашем цикле, когда это возможно, это будет работать только для итераторов, которые моделируют итератор произвольного доступа, что означает, что вы не можете изменить свой код для использования, например.а std::list
.
Да, это возможно, и на самом деле необходимо использовать указатели, если вы хотите, чтобы ваш вектор содержал объекты из всей иерархии классов, а не из одного типа. (Отказ от использования указателей приведет к страшной проблеме нарезки объектов - все объекты работают без вывода сообщений преобразован в тип базового класса. Это не диагностируется компилятором и почти наверняка не то, что вам нужно.)
class c
{
void virtual func();
};
class sc:public c
{
void func(){cout<<"using func";}
};
sc cobj;
vector<c*> cvect; // Note the type is "c*"
cvect.push_back(&cobj); // Note the "&"
vector<c*>::iterator citer;
for(citer=cvect.begin();citer != cvect.end();citer++) // Use "!=" not "<"
{
(*citer)->func();
}
Обратите внимание, что с вектором указателей, вам необходимо самостоятельно управлять памятью , поэтому будьте очень осторожны - если вы будете использовать локальные объекты (как указано выше), они не должны выпадать области видимости до контейнера. Если вы используете указатели на объекты, созданные с помощью new
, вам нужно delete
вручную их удалить, прежде чем контейнер будет уничтожен. В этом случае вам обязательно следует использовать интеллектуальные указатели, например smart_ptr
, предоставленные Boost
. р>
Да, конечно.
// TestCPP.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
#include <vector>
using namespace std;
class c
{
public:
void virtual func() = 0;
};
class sc:public c
{
public:
void func(){cout<<"using func";}
};
int _tmain(int argc, _TCHAR* argv[])
{
sc cobj;
vector<c*> cvect;
cvect.push_back(&cobj);
vector<c*>::iterator citer;
for(citer=cvect.begin();citer<cvect.end();citer++)
{
(*citer)->func();
}
return 0;
}
Обратите внимание на объявление vector<c*> cvect
и использование cvect.push_back(&cobj)
.
Из предоставленного кода вы неправильно используете итератор. Чтобы получить доступ к члену, на который указывает итератор, вы должны использовать *citer
вместо citer
.
Вы создали vector<c*>
для вектора указателей. Затем используйте new
для выделения памяти для объектов c и вставьте их в вектор. Кроме того, не забывайте, что вы должны delete
себя и vector.clear () не освободит память, выделенную для объектов c. Здесь вы должны хранить c как вектор указателей, иначе вызов виртуальной функции не будет работать.
Попробуйте библиотеку контейнеров для повышения указателей , Он имеет несколько преимуществ перед обычным вектором указателей, например:
my_container.push_back( 0 ); // throws bad_ptr
ptr_vector<X> pvec;
std::vector<X*> vec;
( *vec.begin() )->foo(); // call X::foo(), a bit clumsy
pvec.begin()->foo(); // no indirection needed