Почему мне разрешено создавать несколько уникальных указателей из одного объекта? - PullRequest
22 голосов
/ 29 марта 2019

Почему мне разрешено создавать несколько уникальных указателей из одного объекта?

#include <iostream>
#include <memory>

using namespace std;    

class Class
{
public:
    Class(int a): int_(a){std::cout << "constr" << std::endl;}
    ~Class(){std::cout << "destr" << std::endl;}
    int int_;

};

int main()
{
    Class a(4);
    std::unique_ptr<Class> ptr = std::make_unique<Class>(a);
    std::unique_ptr<Class> ptr2 = std::make_unique<Class>(a);
    std::unique_ptr<Class> ptr3 = std::make_unique<Class>(a);
    std::cout << ptr->int_ << std::endl;
    std::cout << ptr2->int_ << std::endl;
    std::cout << ptr3->int_ << std::endl;

    return 0;
}

Вывод:

constr
4
4
4
destr
destr
destr
destr

Ответы [ 3 ]

40 голосов
/ 29 марта 2019

Почему бы и нет?

Вы не создаете несколько экземпляров unique_ptr, указывающих на один и тот же экземпляр Class, но вместо этого выделяете три новых экземпляра Class в куче, созданных с помощью копирования из a. Каждый unique_ptr указывает на другой экземпляр.


std::unique_ptr<Class> ptr = std::make_unique<Class>(a);

Вышеприведенное означает: создайте новый экземпляр Class в куче, скомпонованный из a, и передайте в собственность его новому экземпляру std::unique_ptr с именем ptr.

21 голосов
/ 29 марта 2019

Почему мне разрешено создавать несколько уникальных указателей из одного объекта?

Вам не разрешено это делать *, поэтому хорошо, что вы не делает это!

Не забывайте, это:

std::unique_ptr<Class> ptr = std::make_unique<Class>(a);

это **:

std::unique_ptr<Class> ptr(new Class(a));

не так:

std::unique_ptr<Class> ptr(&a);

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

tl; dr: Вы создаете копии a.

* Что ж, с бездействующим удалителем вы можете сделать это безопасно, но давайте сохраним этот разговор на другой день ...
**Более или менее…

11 голосов
/ 29 марта 2019

Почему мне разрешено создавать несколько уникальных указателей из одного объекта?

Вам разрешено делать несколько копий объекта, потому что класс можно копировать.


«Уникальный» в unique_ptr не означает, что указанный объект является уникальным экземпляром своего класса. Это означает, что никакой другой указатель не должен обладать указанным объектом. В вашем примере каждый уникальный указатель указывает на отдельный экземпляр; каждый из них принадлежит одному указателю.

Вы могли бы нарушить уникальность следующим образом:

std::unique_ptr<Class> ptr(&a);

Could : Программа будет правильно сформирована, и для ее компиляции потребуется компилятор. Но тогда поведение программы будет неопределенным, поэтому вам очень не следует делать это.

...