Общий указатель из статической функции

Я пытаюсь улучшить свой код, используя интеллектуальные указатели, и в настоящее время пытаюсь заменить все старые необработанные указатели в нашей устаревшей кодовой базе на работе интеллектуальными указателями (std::unique_ptr и std::shared_ptr). Теперь у меня есть случай, когда указатель возвращается из статической функции.

Что произойдет, если я изменю это на std::shared_ptr, которое будет создано с помощью std::make_shared и возвращено из функции?

Сможет ли ref-count достичь 0, поскольку одна ссылка хранится внутри статической функции, или она останется до выхода из программы?

Предыдущий:

static MyObject* MyClass::createPointer()
{
    return new MyObject();
}

Сейчас:

static std::shared_ptr<MyObject> MyClass::createSharedPointer()
{
    return std::make_shared<MyObject>();
}

Вы должны показать нам точный код, чтобы получить точный/точный ответ. C++ слишком сложен, чтобы дать ответ, основываясь только на описании проблемы. Фрагмент кода сделает ваше сообщение более кратким. См. минимально воспроизводимый пример .

user12002570 20.02.2024 08:26

Поделитесь конкретикой.

Chukwujiobi Canon 20.02.2024 08:28

@user12002570 user12002570 Я добавил фрагмент кода, показывающий, как выглядит статическая функция.

André Lehto 20.02.2024 08:30
In my mind it will not be cleaned up until the program exits. Нет. Он будет удален, как только ref-count достигнет 0.
Iman Abdollahzadeh 20.02.2024 08:41

@ImanAbdollahzadeh Точно, и поскольку статическая функция будет существовать до выхода из программы, ref-count никогда не станет равным 0.

André Lehto 20.02.2024 08:43

Вы неправильно поняли. Статическая функция не содержит ссылку на созданный указатель std::make_shared.

Chukwujiobi Canon 20.02.2024 08:51

Можете ли вы удалить static из функции? То, что вы показали, кажется ненужным.

Iman Abdollahzadeh 20.02.2024 08:51

@ChukwujiobiCanon Нет? Будет ли оно передано тому std::shared_ptr, которому будет присвоено возвращаемое значение?

André Lehto 20.02.2024 09:02

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

Pepijn Kramer 20.02.2024 10:11

@ImanAbdollahzadeh: Это неправильный путь. Эта функция-член не нуждается в this, поэтому она должна быть static.

MSalters 20.02.2024 13:31
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
10
337
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

В старом коде возникает утечка памяти при следующем условии:

static MyObject* MyClass::createPointer()
{
    return new MyObject(); /* <—- memory leak */
}

Вы в конечном итоге delete то MyObject, которое создали? Если программа завершится, а вы этого не сделаете, то произойдет утечка памяти. Это не переменная static, а переменная dynamic, поэтому вы несете ответственность за delete.

На мой взгляд, он не будет очищен до выхода из программы.

В старом коде он даже не очистится, пока вы не очистите его сами.

В новом коде:

static std::shared_ptr<MyObject> MyClass::createSharedPointer()
{
    return std::make_shared<MyObject&gt();
}

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

Сможет ли ref-count достичь 0, поскольку одна ссылка хранится внутри статической функции, или она останется до выхода из программы?

Внутри статической функции нет ссылки. В этом случае статическая функция ничем не отличается от нестатической функции.

Сама функция не ведет подсчет ссылок на создаваемый ею std::shared_ptr. Это делает std::shared_ptr, и это деталь реализации.

В старом коде указатель удаляется, но это не относится к вопросу, который я задаю. Что касается вашего вопроса, почему это статическая функция, у меня нет для вас ответа. Это было написано 15 лет назад человеком, который, вероятно, уже вышел на пенсию.

André Lehto 20.02.2024 08:54

Я думаю, он был отмечен тегом static, потому что его нельзя было использовать где-либо еще во всем проекте.

Iman Abdollahzadeh 20.02.2024 08:55

@ImanAbdollahzadeh Я думаю, что они установили его как static, потому что хотели вызвать функцию без необходимости создания экземпляра объекта.

André Lehto 20.02.2024 08:58

@ChukwujiobiCanon Возвращаюсь к моему первоначальному вопросу. Поскольку std::make_shared создается внутри статической функции, не достигнет ли ref_count 0 до выхода из программы?

André Lehto 20.02.2024 09:00

@AndréLehto Я не такой уж эксперт в этом, но я предполагаю, что ваша функция static только создавала shared_ptr и все остальные usages этой памяти, увеличивая и уменьшая ref-count

Iman Abdollahzadeh 20.02.2024 09:04

Нет, функция сама по себе не ведет подсчет ссылок на создаваемый ею std::shared_ptr. Таким образом, сама статическая функция не будет иметь никакого влияния на количество ссылок созданного ею std::shared_ptr.

Chukwujiobi Canon 20.02.2024 09:07

@ChukwujiobiCanon Хотите ли вы создать комментарий, разъясняющий этот вопрос, и я отмечу его как решение?

André Lehto 20.02.2024 09:11

Я предполагаю, что вы тоже проголосуете :). Хорошо, речь идет о std::shared_ptr и о том, как интеллектуальный указатель обрабатывает подсчет ссылок, чтобы знать, когда delete динамически выделяемую переменную, на которую он указывает. Когда создается std::shared_ptr, он сохраняет счетчик ссылок равным 0. Всякий раз, когда он копируется, он увеличивает этот счетчик ссылок, а всякий раз, когда он выходит за пределы области действия, он уменьшает этот счетчик ссылок. Если счетчик ссылок равен 0 и выходит за пределы области видимости, это deletes память, на которую он указывает.

Chukwujiobi Canon 20.02.2024 09:34

@ChukwujiobiCanon: У тебя static логика неправильная. Вы отмечаете функцию static, если она использует только члены класса static и не использует члены объекта (или this->). Эта функция настолько проста, что использует только конструктор. Для этого не требуется экземпляр объекта; на самом деле конструктор — это то, как вы создаете новый экземпляр объекта.

MSalters 20.02.2024 14:02

@MSalters Я все это понимаю, поэтому для начала попросил ОП. Из разговоров, которые у нас были в комментариях, вы увидите, что мы указали на это. ОП говорит: «У меня нет вам ответа. Оно было написано 15 лет назад кем-то, кто, вероятно, уже вышел на пенсию». сначала я думал, что это сделано для внутренней связи, но ОП указал, что эта функция является функцией-членом.

Chukwujiobi Canon 20.02.2024 14:26
Ответ принят как подходящий

Не волнуйся. Современный компилятор C++ выполнит копирование в соответствии с вашим шаблоном кода. Неважно, статическая это функция или нет.

Но для std::shared_ptr необходимо его чему-то присвоить, иначе счетчик ссылок будет равен 0 (немедленное уничтожение объекта).

#include <memory>
#include <iostream>
struct MyObject
{
    MyObject(int i):member{i}{

    }
    ~MyObject(){
        std::cout << "MyObject#" << member << " destruct\n";
    }

    static std::shared_ptr<MyObject> createPointer(int i){
        return std::make_shared<MyObject>(i);
    }
    int member = 0;

   
};

static std::shared_ptr<MyObject> get_singleton_ptr(){
    static auto ptr = std::make_shared<MyObject>(3);
    return ptr;
}

MyObject& get_singleton_ref(){
    static auto ptr = std::make_unique<MyObject>(4);
    return *ptr;
}

int main() {
    MyObject::createPointer(1);

    auto ptr = MyObject::createPointer(2);

    get_singleton_ptr();

    get_singleton_ref();

    std::cout << "end program/scope\n";
}

Результат должен быть

MyObject#1 destruct
end program/scope
MyObject#2 destruct
MyObject#4 destruct
MyObject#3 destruct

Логика «немедленно уничтожить объект» неверна. Если ваш shared_ptr не присвоен переменной, а является временным, то объект, на который указывает, уничтожается в конце полного выражения. Т.е. std::cout << *( std::make_shared<int>(42)); безопасно. Объект int уничтожается не сразу, а только после того, как он будет напечатан.

MSalters 20.02.2024 14:06

Другие вопросы по теме