2015-12-17 2 views
12

std::unique_ptr::operator-> имеет подписьПочему оператор unique_ptr-> не const-overloaded?

pointer operator->() const noexcept; 

Так operator-> является Const, но возвращает изменяемый указатель. Это позволяет использовать код:

void myConstMemberFunction() const 
{ 
    myUniquePtrMember->nonConstFunction(); 
} 

Почему стандарт позволяет это, и как лучше всего предотвратить использование, как указано выше?

+0

Я ожидал, что это потому, что оператор '.' не может быть перегружен. – erip

+2

В C++ 'const' неглубоко. «Int * const» также позволяет вам изменять направленный объект. –

+4

Тот же код будет разрешен, если указатель не был умным. Устойчивость применяется к указателю, а не к указателю. – juanchopanza

ответ

17

Подумайте об этом, как обычный указатель:

int * const i; 

является const указатель на не- constint. Вы можете изменить int, но не указатель.

int const * i; 

является не- const указатель на constint. Вы можете изменить указатель, но не int.


Теперь для unique_ptr, это вопрос о том, const идет внутри или снаружи <>. Таким образом:

std::unique_ptr<int> const u; 

как первый. Вы можете изменить int, но не указатель.

Что вы хотите:

std::unique_ptr<int const> u; 

Вы можете изменить указатель, но не int. Или, возможно, даже:

std::unique_ptr<int const> const u; 

Здесь вы не можете изменить указатель илиint.


Обратите внимание, что я всегда размещаю const справа? Это немного необычно, но необходимо иметь дело с указателями. const всегда относится к предмету сразу слева от него, будь то * (указатель const) или int. См. http://kuhllib.com/2012/01/17/continental-const-placement/.

Дать const int, может привести вас к мысли int const * является const -указатель к не- constint, что неправильно.

7

Это повторяет семантику традиционных указателей. Указатель const - это указатель, который не может быть изменен. Тем не менее, объект, на который он указывает, может.

struct bar { 
    void do_bar() {} 
}; 

struct foo { 
    void do_foo() const { b->do_bar(); } // OK 
    bar* const b; 
}; 

Чтобы избежать мутаций pointee, вам нужен unique_ptr эквивалента константного указателя на константный или

const std::unique_ptr<const bar> b;