2017-01-09 3 views
0

Я смотрел VID о смарт-указатели (VID ссылка ниже), который идентифицирует следующую задачу с традиционными C++ указатели:Как сказать, к какому классу принадлежит указатель

Вы не можете сказать, кто владеет указатель

Hebert продолжает приводить следующий пример: класс A имеет указатель на float, класс B имеет указатель на тот же самый float. Кто из двух владеет указателем? Ну, вы не можете сказать ... это непонятно ... мы не знаем, чья работа - это удалить указатель .. .bad .. запутанный .. трудно отлаживать.

О чем он говорит? Как мы не можем сказать, какой класс владеет указателем? Если указатель создается как часть экземпляра класса A или B, то не будет ли он просто A-> myPointer и B-> myPointer соответственно?

Thx: ^) Кит

https://www.youtube.com/watch?v=Jc9n9BcYSj4
Около 1:00

EDIT

#include <iostream> 
class A { 
public: float * f_ptr; 
}; 
class B { 
public: float * f_ptr; 
}; 
int main() { 
    float f=2.71; 
    A* a = new(A); 
    B* b = new(B); 
    a->f_ptr = &f; 
    b->f_ptr = &f; 
    std::cout << "a->f_ptr: " << *a->f_ptr << std::endl; 
    std::cout << "b->f_ptr: " << *b->f_ptr << std::endl; 
    delete a; 
    delete b; 
    std::cout << std::endl; 
} 

/************ 
OUTPUT 

a->f_ptr: 2.71 
b->f_ptr: 2.71 

*/ 

EDIT 2

Следующая запись объясняет это явление очень хорошо:
http://ericlavesson.blogspot.com/2013/03/c-ownership-semantics.html

+0

Они означают, на что указывает указатель. И я предполагаю, что это предполагает, что кому-то, кроме того, что указал сам объект, владеет им. – juanchopanza

+0

raw указатель может иметь только одного владельца, так кто же является владельцем? A или B? –

+1

Да, но проблема в том, что один из классов должен удалить указатель, но не до того, как другой класс перестанет его использовать. Откуда нам знать? Умный указатель мог понять это. –

ответ

1

Когда он говорит, что какой-то класс «владеет указателем», это означает, что этот класс отвечает за очистку беспорядка, который делает указатель. У вас могут быть два разных класса A и B, которые используют указатель, указывающий на тот же объект. Если вы не являетесь разработчиком этих классов, вы не можете определить, какой из них следует удалить в конце и выполнить очистку после него, например. разблокирование некоторых ресурсов. Вы не можете понять это или установить его, используя некоторую встроенную семантику языка - вам нужно сказать об этом, например. через документацию.Если дизайн плохой, вы можете получить два класса, пытающихся очистить после одного и того же объекта дважды или не очистить после объекта вообще.

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

+0

Благодарим вас за объяснение сценария, обсуждаемого в видео.Этот вопрос, очевидно, имеет далеко идущие последствия и может разворачиваться во множество разных дискуссий, но ваш ответ ответил на мой вопрос. – kmiklas

+0

Нет проблем. Рад, что я мог бы помочь. – KjMag

1

Хорошо или плохо, но языки C и C++ не устанавливают никаких правил владения памятью, на которую указывают указатели. Это имеет далеко идущие последствия. На сегодняшний день слишком поздно устанавливать какие-либо правила здесь. Тонны и тонны существующего кода будут нарушены.

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

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

1

Существует разница между самим указателем (адресом) и указываемой памятью.

Каждый класс владеет указателем, но никто не имеет технически владеющего остроконечной памятью. Это должно быть как-то ( ), если он нераспределен, это segfault, если он освобожден дважды, он свободен от двойки, и если он вообще не освобождается, это утечка памяти), но это зависит исключительно от программиста. Можно создать класс, ответственный за некоторую память (путем управления конструктором и деструктором этого класса), но это чисто конвенция, а не язык. В других классах не будет отказано в праве освобождать или перераспределять эту память, если им предоставляется копия адреса/указателя (хотя это, как правило, очень плохая идея).

1

Умные указатели редко являются решением указанной проблемы. Однако они часто являются решением другой проблемы.

Проблема, изложенная здесь, является проблемой общей собственности. Когда и A, и B 'собственный' ресурс, кто отвечает за его освобождение? std::shared_pointer - указатель подсчета ссылок, который освободит ресурс, как только все его пользователи уйдут. Однако этого сценария следует избегать. Поделившись указателями в программе, крайне сложно спорить о времени жизни ресурса. Хотя при использовании shared_pointer (как правило, случая с многопоточными очередями) бывает мало случаев, лучше попытаться избежать совместного владения - как в реальной жизни, кстати :). Вместо этого сделайте один класс владельцем, а другой - пользователем, и создайте свой интерфейс таким образом, чтобы пользователи никогда не переживали владельцев. Это не так сложно, как может показаться, и этот дизайн окупится в упрощении обслуживания программы.

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

Смежные вопросы