Когда использовать слабый_птр вместо вызова по ссылке - PullRequest
2 голосов
/ 12 июня 2019

Я объявил класс сериализации с помощью следующих методов, но еще не реализовал его:

    const std::string toJson(const Location &obj);

    const std::string toJson(std::weak_ptr<const Location> obj);

    const std::string toJson(std::shared_ptr<const Location> obj);

Работа класса сериализации, как ни удивительно, заключается в преобразовании одного представления в другое, например, изJson классу C ++ и наоборот.

Теперь где-то еще в моем коде я беру уникальное право собственности, как это:

    std::unique_ptr<Location> uniqueLocation = getLocation();

Теперь мой вопрос: сериализация не нужнавзять на себя ответственность за unique_ptr.Какой метод он должен вызывать?ToJson, использующий weak_ptr, или toJson по ссылке?

Ответы [ 3 ]

4 голосов
/ 12 июня 2019

Вы не можете создать std::shared_ptr из std:::unique_ptr (если только вы release() не владеете им в первую очередь), и вы вообще не можете создать std::weak_ptr из std::unique_ptr, только из std::shared_ptr. Так что остается только один вариант:

const std::string toJson(const Location &obj);

Это имеет смысл, поскольку вам не нужно или вы не хотите, чтобы toJson() принял / поделился владением объектом Location, просто чтобы использовать его как есть.

Если честно, другие перегрузки на самом деле не имеют особого смысла. Вызывающий должен решить, как ему получить ссылку на объект Location, а затем при необходимости передать фактический объект в toJson(), например:

std::unique_ptr<Location> uniqueLocation = getLocation();
std::string s = toJson(*uniqueLocation);

Но, если вы хотите сохранить перегрузки, просто попросите их делегировать одну перегрузку, которая принимает ссылку на объект:

const std::string toJson(const Location &obj)
{
    // do the actual work here...
}

const std::string toJson(std::weak_ptr<Location> obj)
{
    std::shared_ptr<Location> sp = obj.lock();
    return toJson(sp);
}

const std::string toJson(const std::shared_ptr<Location> &obj)
{
    std::string s;
    if (obj)
        s = toJson(*obj);
    return s;
}

const std::string toJson(const std::unique_ptr<Location> &obj)
{
    std::string s;
    if (obj)
        s = toJson(*obj);
    return s;
}
3 голосов
/ 12 июня 2019

weak_ptr является дополнением к shared_ptr и здесь вам не поможет.

Вы можете использовать первую перегрузку или передать unique_ptr сам по ссылке.

Даже если бы вы использовали shared_ptr вместо unique_ptr, я бы посоветовал то же самое.Раньше я хранил weak_ptr s в контейнерах (или захватывал их в лямбдах), но если вы просто переходите к функции, требующей некоторой работы, это кажется ненужными накладными расходами.

Мнение Херба по этому вопросу может представлять интерес для вас.

0 голосов
/ 12 июня 2019

Интеллектуальные указатели относятся к владению.

Владение - к пожизненному сроку.

const std::string toJson(const Location &obj);

Это говорит «вы передадите obj, который является действительным Location, и эта функцияобещает не менять его ".

Возвращаемое значение - const std::string - является токсичным анти-паттерном.Не делай этого.Возврат std::string.

std::string toJson(std::weak_ptr<const Location> obj);

Это заявляет: «Я возьму, возможно, допустимую ссылку на obj, который я буду точно хранить где-то. В какой-то неизвестный момент в будущем я проверю, по-прежнему ли этот объектсуществует и создайте общий указатель на него.После вызова этой функции не предполагайте, что время жизни указанного в obj закончится в любом контролируемом месте, но обычно я буду вежлив и не буду удерживать сгенерированныйshared_ptr для более короткого бита ".

std::string toJson(std::shared_ptr<const Location> obj);

Это говорит:" Я хочу участвовать в совместном управлении указанным obj. obj имеет и должен иметь сложный срок службы, которыйне может быть легко выражено через простое владение. Я попытался использовать более простые модели владения, но они не отражают истинную сущность того, как долго obj должен выжить, поэтому я использую указатели с подсчетом ссылок. "

std::unique_ptr<Location> uniqueLocation = getLocation();

Это говорит: «Я хочу контролировать владение этим объектом, который никогда не был в сложной ситуации владения. Если бы я мог, я был бы ценностью (или, может быть,необязательно), но некоторые проблемы не позволяют мне быть ценным.Так что я буду уникальным указателем на значение. "

Сериализации не нужно вступать во владение unique_ptr. Какой метод он должен вызывать??

Функция, которая конвертирует вещи в Json, вероятно, просто нуждается в конвертируемом объекте, чтобы быть действительной для длины вызова.

toJson(const Location&) - это та, которая означает это.

...