2015-12-23 3 views
1

Начиная с точки зрения идиомы «не следует использовать исходные указатели», я смотрел на умные указатели, чтобы найти, какой из них лучше всего подходит для отношений «обратный».Как выразить в Modern C++ ссылки на отношения без выражения собственности?

К относятся к отношениям, я имею в виду то же самое, как этот код:

class A 
{ 
public: 

    A(B & b) : 
     m_refB(b) 
    { } 

private: 

    B & m_refB; // A refers to B 
}; 

Но без всех недостатков использования ссылок (впоследствии не может быть переплетен, не может быть переназначен, А больше не может быть по умолчанию конструктивны и т.д).

Каждый умный указатель, однако, в своей собственной семантике выражает концепцию собственности. Они даже называются вокруг этой концепции собственности (уникальный указатель, когда собственность уникальна только для одного объекта, общий указатель, когда собственность делится между другими объектами и т. Д.).

Я хотел бы выразить, что A относится к B, но A не принадлежит B. Может ли std::reference_wrapper<B> выполнить эту работу или это было бы неправильным использованием?

+2

'станд :: weak_ptr' не принадлежит собственность – Danh

+0

@Danh ли не' станд :: weak_ptr' применять требование использовать 'зЬй :: shared_ptr' для тот же ресурс? –

+1

@JamesAdkison, это так, и поэтому я не защищаю его за это. См. Мой ответ. – SergeyA

ответ

13

Нет такой вещи, как 'не следует использовать необработанные указатели. Это 'не следует использовать владеет необработанными указателями. Нет ничего плохого в том, что у вас есть необработанный указатель на refer-to idiom. Умные указатели - это просто избыток для этого. Особенно std::weak_ptr :)

+0

Но грубый указатель выглядит как плохой запах. Читатель не может отличить плохой/ленивый/пропущенный код от намерения назначаемой/нулевой/не владеющей ссылки. Хотел бы я найти в GSL non_owning . – MartinP

1

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

Если вы решили, что вам нужно упомянутый объект, который вы можете использовать lock(), который будет возвращать shared_ptr к объекту и продлить срок службы его до shared_ptr выходит из области видимости.

+2

... но временно наследует объект, пока он его изучает. –

+2

Что еще хуже, для этого требуется, чтобы shared_ptr существовал где-то. – SergeyA

1

Я думаю, что answer предоставил @SergeyA и отлично зарекомендовал себя.

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

Например:

/** 
* A class that refers to an existing object instance. This class does not own 
* the existing object instance and the lifetime of the existing object instance 
* must be greater than the lifetime of instantiations of this class. 
*/ 
template<typename T> 
class Handle 
{ 
public: 
    Handle(T& object) : mObject(&object) {} 

    // ... other functions necessary to use this object ... 

private: 
    T* mObject; 
}; 
+0

Но у нас уже есть ['std :: reference_wrapper'] (http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper).Или это слишком тяжело? – LogicStuff

+1

@LogicStuff Я не могу ответить. Я просто не полностью осведомлен о всех новых материалах 'C++', поэтому, возможно, я непреднамеренно изобрел колесо. Спасибо, я посмотрю на 'std :: reference_wrapper'. –

+0

Существует также ['observer_ptr'] (http://en.cppreference.com/w/cpp/experimental/observer_ptr), хотя я не знаю, попадет ли он в стандартную библиотеку. – juanchopanza