Назад к вопросам
Middle
109
questionbank

Можно ли изменить владельца объекта, на который указывает unique_ptr?

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Да, можно. Владельца unique_ptr можно изменить одним из следующих способов:

  1. Передача владения с использованием std::move: Новый unique_ptr может получить владение у существующего unique_ptr. При этом старый unique_ptr становится пустым (нулевым).

    #include <memory>
    
    int main() {
        auto ptr1 = std::make_unique<int>(10);
        auto ptr2 = std::move(ptr1); // ptr2 теперь владеет объектом, ptr1 пустой
    
        // Объект с значением 10 теперь принадлежит ptr2
        // ptr1 больше не указывает на объект
    
        return 0;
    }
    
  2. Сброс и присваивание: Можно сбросить текущий unique_ptr (освободив владение и удалив объект), а затем присвоить ему либо новый объект, либо владение от другого unique_ptr (снова используя std::move).

    #include <memory>
    
    int main() {
        auto ptr1 = std::make_unique<int>(10);
        auto ptr2 = std::make_unique<int>(20);
    
        ptr1.reset(); // ptr1 становится пустым, объект {10} удаляется
        ptr1 = std::move(ptr2); // ptr1 теперь владеет объектом {20}, ptr2 пустой
    
        return 0;
    }
    

    Метод reset(pointer) также позволяет передать владение новым объектом или указателем из внешнего источника, при этом текущий объект освобождается.

    #include <memory>
    
    int main() {
        auto ptr1 = std::make_unique<int>(10);
        int* raw_ptr = new int(20); // создаем объект вне unique_ptr
    
        ptr1.reset(raw_ptr); // ptr1 теперь владеет объектом {20}, объект {10} удаляется
    
        return 0;
    }
    
  3. Извлечение "сырого" указателя с помощью release(): Метод release() возвращает "сырой" указатель на объект, которым владеет unique_ptr, и при этом отказывается от владения. unique_ptr становится пустым. Затем этот "сырой" указатель может быть передан другому объекту, который примет владение, например, другому unique_ptr или ручному управлению памятью (с последующим delete). Важно: если полученный сырой указатель не будет передан объекту, который примет владение, возникнет утечка памяти.

    #include <memory>
    
    int main() {
        auto ptr1 = std::make_unique<int>(10);
        int* released_ptr = ptr1.release(); // released_ptr указывает на {10}, ptr1 пустой
    
        auto ptr2 = std::unique_ptr<int>(released_ptr); // ptr2 принимает владение released_ptr
    
        // Объект с значением 10 теперь принадлежит ptr2
        // released_ptr не нужно удалять вручную, так как ptr2 теперь им владеет
    
        return 0;
    }
    

Таким образом, unique_ptr гарантирует уникальное владение, но позволяет явным образом передать это владение из одного экземпляра в другой.