2015-12-17 12 views
12

std::unique_ptr::operator-> ma sygnaturęDlaczego operator unique_ptr-> not const-overloaded?

pointer operator->() const noexcept; 

Więc operator-> jest const ale zwraca zmienny wskaźnik. Pozwala to na kod taki jak:

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

Dlaczego standard pozwala na to i jaki jest najlepszy sposób na zapobieganie użyciu, jak przedstawiono powyżej?

+0

spodziewałem się, że to dlatego, że operator '.' nie może być przeciążony. – erip

+2

W języku C++ 'const' jest płytkie. "Int * const" pozwala także modyfikować wskazany obiekt. –

+4

Ten sam kod byłby dozwolony, gdyby wskaźnik nie był sprytny. Stała odnosi się do wskaźnika, a nie do wskażnika. – juanchopanza

Odpowiedz

17

Pomyśl o tym jak normalny wskaźnik:

int * const i; 

jest const wskaźnik do nieprzestrzegania constint. Możesz zmienić wartość int, ale nie wskaźnik.

int const * i; 

jest nie- const wskaźnik do constint. Możesz zmienić wskaźnik, ale nie zmienić wartości int.


Teraz, unique_ptr, to kwestia, czy const idzie wewnątrz lub na zewnątrz <>. A więc:

std::unique_ptr<int> const u; 

jest jak pierwszy. Możesz zmienić wartość int, ale nie wskaźnik.

Co chcesz to:

std::unique_ptr<int const> u; 

można zmienić wskaźnik, ale nie int. Albo nawet:

std::unique_ptr<int const> const u; 

Tutaj nie można zmienić wskaźnik lubint.


Zauważ, jak zawsze umieszczam const po prawej? Jest to trochę niecodzienne, ale jest konieczne, gdy mamy do czynienia ze wskaźnikami. const zawsze odnosi się do rzeczy bezpośrednio po lewej stronie, czy to * (wskaźnik to const), czy int. Zobacz http://kuhllib.com/2012/01/17/continental-const-placement/.

Pisanie const int, może prowadzić do myślenia int const * jest const -pointer do niebędącego constint, co jest nie tak.

7

Powielenie semantyki tradycyjnych wskaźników. Wskaźnik const to wskaźnik, którego nie można zmutować. Jednak obiekt, na który wskazuje, może.

struct bar { 
    void do_bar() {} 
}; 

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

Aby uniknąć mutowania wskazywanego, musisz unique_ptr równowartość const wskaźnik do const lub

const std::unique_ptr<const bar> b; 
Powiązane problemy