уникальный указатель против необработанного указателя - PullRequest
0 голосов
/ 30 декабря 2018

Попытка понять unique_pointer против доступа к необработанному указателю

#include <iostream>
#include <memory>

int main() {
    int a = 10;
    int *x = &a;
    int *y = &a;
    std::unique_ptr<int> p1 = std::make_unique<int>(a);
    std::cout<<*x<<*p1<<*y<<"\n";
    // prints 101010
    *p1 = 20;
    std::cout<<*x<<*p1<<*y<<"\n";
    // prints 102010
    *x =30;
    std::cout<<*x<<*p1<<*y<<"\n";
    // 302030
    return 0;
}

Вывод

101010
102010
302030

Program ended with exit code: 0

В приведенном выше коде x, y, p1 все указывают на переменную a;поэтому изменение значения a должно отражаться на разыменовании всех указателей.

Пожалуйста, помогите мне понять поведение. Я - немногие из тех парней, которые сейчас переходят от использования необработанных указателей к умным указателям.

Ответы [ 2 ]

0 голосов
/ 30 декабря 2018

Причина

  • std::make_unique() позволяет создавать новый объект, не ссылаясь на параметр

Решение

  • , как сказал Some programmer dude, используйте std::unique_ptr<int> p1(&a);
    • , в результате уникальный_ptr указывает на тот же адрес: скриншот
0 голосов
/ 30 декабря 2018

Вы ошибаетесь, p1 не указывает на a.

Вместо std::make_unique<int>(a) создайте новый объект int и инициализируйте его текущим значением из a.


Чтобы p1 указать на a, вам нужно сделать

std::unique_ptr<int> p1(&a);

Однако это влечет за собой другие проблемы, такие как p1захват владения из &a и попытка освободить эту память при разрушении p1 (что невозможно).

Вы можете использовать Повышение null_deleter, чтобы избежать последней проблемы.

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

...