Изменение указывает на переменную unique_ptr

Я не думаю, что правильно понял концепцию умных указателей.

Взгляните на этот MWE:

// Example program
#include <iostream>
#include <memory>
#include <string>

struct P{
    float x, y;
    P() : x(0.f), y(0.f){}
    P(float x, float y) : x(x), y(y){}
    P(P&& q) : x(q.x), y(q.y){}
    P& operator=(P&& q){
        x = q.x;
        y = q.y;
        return *this;
    }
    P& operator=(const P&) = delete;
    P(const P&) = delete;

};

std::ostream& operator<<(std::ostream& out, const P& p){ out << p.x << " / " << p.y; return out;}

int main(){    
    P p1{1.f, 0.f};
    P p2{2.f, 0.f};

    std::unique_ptr<P> p1Ptr(std::make_unique<P>(std::move(p1)));
    P* p2Ptr = &p2;

    p1 = std::move(P{1.f, 1.f});
    p2 = std::move(P{2.f, 2.f});

    std::cout << " p1: " << p1 << "\n";
    std::cout << "*p1: " << *p1Ptr << "\n";
    std::cout << "*p1: " << *(p1Ptr.get()) << "\n";
    std::cout << " p2: " << p2 << "\n";
    std::cout << "*p2: " << *p2Ptr << std::endl; 
}

Выход:

p1: 1 / 1
*p1: 1 / 0
*p1: 1 / 0
p2: 2 / 2
*p2: 2 / 2

Я ожидал, что std::unique_ptr также увидит изменение значения p1. Тем не менее, это не так. Как я могу этого добиться?

Указатель p1ptr указывает на совершенно другой объект типа P. Он вообще не указывает и не ссылается на p1. *p1ptr и p1 - два разных и отдельных объекта.

Some programmer dude 02.07.2019 14:09

обратите внимание, что ходы избыточны, p1 = P{1.f, 1.f}; уже является назначением хода.

Caleth 02.07.2019 14:21

Это проблема XY — зачем вам std::unique_ptr, чтобы указать на существующий объект? Это побеждает его цель.

Slava 02.07.2019 14:27

@Слава, если вы пытаетесь владеть структурой, в которой не определен ctor, то у вас нет другого выбора, кроме как указать на существующий объект? stackoverflow.com/questions/55141594/…

simplename 12.01.2022 18:15
Стоит ли изучать 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 называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
840
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

p1Ptr на самом деле не указывает на объект p1. Он указывает на безымянный объект, созданный std::make_unique с помощью конструктора P(P&&).

Нет смысла иметь точку std::unique_ptr<T> на объекте, определенном локально по отношению к функциональному блоку. Вся причина unique_ptr в том, что это единственный владелец объекта, на который он каким-то образом указывает. Поскольку вы используете средство удаления по умолчанию, это владение означает, что unique_ptr будет delete указателем на свой объект, пытаясь завершить свое время жизни. Но локальный объект функции уже имеет свое время жизни, «принадлежащее» функциональному блоку, и будет автоматически уничтожен, когда выполнение покинет этот блок; недействителен delete указатель на такой объект.

Итак, если мне нужны указатели на элементы в векторе, лучше использовать необработанные указатели?

infinitezero 02.07.2019 14:49

Интеллектуальные указатели @infinitezero представляют владение, уникальное или совместно используемое, если вы просто указываете, но не используете необработанные указатели. Кстати, не рекомендуется иметь указатели на элементы в векторе из-за перераспределения.

Slava 02.07.2019 15:02

Элементы в std::vector также уже «принадлежат», на этот раз vector.

aschepler 02.07.2019 15:31

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