Я знаю, что unique_ptr делает интеллектуальный указатель владельцем ресурса и, следовательно, не позволяет нескольким указателям указывать на один и тот же ресурс.
Но почему тогда можно создать необработанный указатель на этот умный указатель с помощью .get(), а затем передать его функции?
В конце у вас есть два указателя, которые владеют ресурсом и имеют возможность изменять его значение? Это нарушит правило unique_ptr smart ptr, владеющего исключительно ресурсом.
В примере ниже я создал простую программу, которая изменяет значение, на которое указывает указатель smrt smrtPtr.
Бывший:
#include <iostream>
#include <memory>
#include <utility> //move semantics
void changeValue(int* ptr)
{
if (!ptr) //check if pointer is null
return;
*ptr = 17; //change value to 17
}
int main()
{
auto smrtPtr{ std::make_unique<int>(5) };
changeValue(smrtPtr.get()); //creates a raw pointer of smrtPtr
if (smrtPtr) //if it does contain resource
std::cout << *smrtPtr;
return 0;
}
Большое спасибо
Важное чтение: Что такое владение ресурсами или указателями?
большое спасибо, но, например, интеллектуальный указатель std::weak_ptr также не владеет ресурсом, но ему не разрешено использовать один и тот же ресурс с одним интеллектуальным указателем std::unique_ptr?
Чтобы получить указатель из weak_ptr, вам нужно получить shared_ptr из weak_ptr, если можете, а затем получить указатель из shared_ptr. Если вы взяли этот указатель, а затем поместили его в unique_ptr, у вас теперь есть конфликтующие владельцы: unique_ptr освободит ресурс, когда он выйдет за пределы области действия, а последний shared_ptr также освободит ресурс. В лучшем случае программа терпит двойную бесплатность, но вам не повезет, если вы зайдете так далеко. Необработанный указатель освобождает ресурс только тогда, когда вы явно вызываете к нему delete.
@ tadm123 weak_ptr не имеет смысла, поскольку участвует в семантике владения. Способ подключения к нему — это блок управления, который создается при создании shared_ptr. Поскольку ничто другое не должно владеть unique_ptr, на 100% можно вернуть необработанный указатель в качестве дескриптора.
Обратите внимание: если вы получаете shared_ptr от weak_ptr, этот shared_ptr является таким же владельцем, как и любые другие связанные shared_ptr. Причина этого в том, чтобы убедиться, что пока вы удерживаете shared_ptr, полученный от weak_ptr, существует хотя бы один экземпляр shared_ptr, поддерживающий работоспособность принадлежащего ресурсу. Никто другой не сможет высвободить его из-под вас, если только он не сделает что-нибудь действительно <ругательство удалено> глупо, например, вручную delete это.
Подводя итог, у вас нет двух указателей-владельцев, потому что необработанный указатель не владеет. И интеллектуальный указатель, и необработанный указатель могут изменяться и использовать указанный ресурс, поскольку ни один из них не является поведением владельца. Только интеллектуальному указателю разрешено действовать как владелец и освобождать указанный ресурс без неприятных последствий.
«и, следовательно, он не позволяет нескольким указателям указывать на один и тот же ресурс». он не делает ничего подобного. Это означает, что интеллектуальный указатель является единственным ВЛАДЕЛЬЦЕМ ресурса и, следовательно, несет исключительную ответственность за определение момента его удаления. Это не имеет никакого отношения к тому, кто может просматривать содержимое.
@ tadm123 «умный указатель std::weak_ptr также не владеет ресурсом» — это достаточно верно; weak_ptr своего рода арендует ресурс вместо того, чтобы владеть им. У него есть соглашение, которое дает ему доступ к ресурсу до тех пор, пока ресурс существует. Однако именно владельцы, а не арендаторы, решают, когда ресурс будет отчужден. Если ресурс пропал и арендатор хочет его получить, ему говорят: «Плохо». Обратите внимание, что по замыслу unique_ptr не сдают свои ресурсы в аренду таким образом.
@ tadm123 tadm123 многие вещи, которые вы говорите «не разрешены», следует называть «неправильными», но это не значит, что плохая программа не может этого сделать.
Обычно есть два фактора, которые заставляют людей спотыкаться при использовании «умных указателей»; 1) они думают о них как об указателях, а не как об объектах с конкретными правилами владения, и 2) они никогда по-настоящему не задумывались о природе владения. (Подумайте, у скольких вещей вокруг вас есть конкретный владелец, а не вы, и тем не менее вы можете их просматривать и даже использовать.)
с возможностью изменения своего значения" Это константность, не связанная с принадлежностью.





Весь ваш вопрос основан на путанице в том, что делает умный указатель:
«и, следовательно, он не позволяет нескольким указателям указывать на один и тот же ресурс».
Ничего подобного не происходит. Интеллектуальный указатель определяет, кому принадлежит ресурс, а не кто может его просматривать.
Ответственность владельца – удалить ресурс в нужный момент. Это означает, что не следует удалять его до того, как будут завершены другие действия по его чтению.
Уникальный указатель означает, что за удаление отвечает только он. Общий указатель означает, что за удаление отвечает последний общий указатель.
Ничто из этого не влияет на возможность доступа к ресурсу.
Стандартная терминология — «право собственности», но я понимаю, что это несколько неточно. В реальном мире часто бывает так, что владелец чего-либо — единственный, кто может это что-то изменить. (Например, большинство домовладельцев были бы расстроены, если бы кто-то пришел и покрасил их дом в новый цвет.) Это не то, что означает «владение» в отношении управления памятью.
Более точным термином могло бы быть «хранитель». Работа хранителя – заботиться о чем-то. Здесь не подразумевается, что «что-то» принадлежит исключительно хранителю, а лишь то, что хранителю приходится следить за тем, чтобы о вещах заботились, например, убираться в конце дня. Это возвращает нас к управлению памятью. «Хранитель» (обычно называемый «владельцем») отвечает за очистку памяти. Время уборки зависит от хранителя, с одной оговоркой. Если существует более одного хранителя (подумайте shared_ptr), существует соглашение, что очистка ложится на последнего вышедшего хранителя. (Хранитель 1: «Я направляюсь домой. Ты запираешься, да?» Хранитель 2: «Да, я этим занимаюсь».)
Когда указатель получается из интеллектуального указателя через get(), этот указатель обеспечивает доступ к хранимому объекту. С этим доступом можно разрешить модифицировать, но не уничтожать, объект. Аналогично, доступ в конференц-зал часто включает в себя разрешение переставлять, но не повреждать, стулья. А может быть, повесить плакаты или другие наглядные пособия. Дело в том, что изменения могут быть внесены. После собрания участники уходят, а хранитель запирается, закрывая весь разрешенный доступ. Это роль интеллектуального указателя — блокировать/завершать разрешенный доступ, когда вокруг больше нет хранителя.
(Причина получения статуса «разрешено» объясняется историей отеля. В конференц-зале можно запереться и получить запрет на доступ. Если окружающая среда не решит снести это место в одночасье.)
Однако уже поздно менять терминологию. Мы застряли на слове «владелец», но если мысль «хранитель» помогает, действуйте.
Необработанные указатели не подразумевают НИКАКОГО владения. В этом их красота и их проклятие.