Получение утечки памяти с моими общими указателями? - PullRequest
0 голосов
/ 01 мая 2019

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

std::vector<std::shared_ptr<Fing*>> files;

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

static std::shared_ptr<Fing*> create(const std::string filetype, const std::string &path);

Производный абстрактный класс Fing * имеет три других производных класса, которые я буду называть производными A, B, C.Так что мой вектор в базовом классе shared_ptr больше похож на вектор shared_ptr<A* or B* or C*>

Так что сам фабричный метод выглядит так:

shared_ptr<Fing*> Fing::create(const std::string fileType, const 
string &filepath){

if (fileType == "a"s){
    return make_shared<Fing*>(new A(filepath));
}
if (fileType == "b"s){
    return make_shared<Fing*>(new B(filepath));
}
    return make_shared<Fing*>(new C(filepath)); }

Я называю фабричный метод как таковой

shared_ptr<Fing*> newA(Fing::create("a","path here"));

и вставьте его в мой вектор вот так

myfiles.emplace_back(move(newA));

Однако, хотя мой базовый класс разрушается, Вальгринд говорит, что естьтечь из моего заводского метода?

Ответы [ 2 ]

3 голосов
/ 01 мая 2019

Проблема в том, что вы не должны указывать, что параметр для std::shared_ptr является указателем, то есть неявным .

То есть ваши объявления должны быть примерно такими:

class Fing
{
public:
    Fing(std::string const&) {}
    virtual ~Fing() {}
};

class A: public Fing { public: A(std::string const& s): Fing(s) {}};
class B: public Fing { public: B(std::string const& s): Fing(s) {}};
class C: public Fing { public: C(std::string const& s): Fing(s) {}};

std::vector<std::shared_ptr<Fing>> files;

std::shared_ptr<Fing> create(const std::string &filepath)
{
    return std::make_shared<A>(filepath);
}
1 голос
/ 01 мая 2019

std::shared_ptr - это интеллектуальный указатель, он содержит внутренний указатель и управляет его временем жизни. Но вы неправильно используете std::shared_ptr. Никогда не следует устанавливать для параметра шаблона T тип указателя, а только фактический тип, на который он должен указывать. Указание на указатель противоречит цели использования интеллектуального указателя.

Вы тоже неправильно используете std::make_shared(). Весь смысл использования std::make_shared() состоит в том, чтобы избежать необходимости использовать new явно, и распределить начальный std::shared_ptr<T> более эффективно, чем сам по себе new. std::make_shared() выделяет указанный вами T, перенаправляя свои собственные аргументы в конструктор T.

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

Попробуйте вместо этого:

std::vector<std::shared_ptr<Fing>> files;

...

std::shared_ptr<Fing> Fing::create(const std::string &fileType, const std::string &filepath)
{
    if (fileType == "a"s){
        return make_shared<A>(filepath);
    }
    if (fileType == "b"s){
        return make_shared<B>(filepath);
    }
    return make_shared<C>(filepath);
}

...

auto newA = Fing::create("a", "path here");
myfiles.push_back(std::move(newA));

or just:

myfiles.push_back(Fing::create("a","path here"));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...