2015-12-17 10 views
12

std::unique_ptr::operator-> ha la firmaPerché l'operatore unique_ptr-> non è sovraccarico di cost?

pointer operator->() const noexcept; 

Così operator-> è const, ma restituisce un puntatore mutevole. Questo consente codice come:

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

Perché lo standard lo consente e qual è il modo migliore per prevenire l'utilizzo come illustrato sopra?

+0

mi aspettavo che sia perché l'operatore '.' non può essere sovraccaricato. – erip

+2

In C++ 'const' è superficiale. Un 'int * const' consente anche di modificare l'oggetto puntato. –

+4

Lo stesso codice sarebbe consentito se il puntatore non fosse intelligente. La costanza si applica al puntatore, non al puntale. – juanchopanza

risposta

17

Pensateci come un normale puntatore:

int * const i; 

è un puntatore ad un const non constint. È possibile modificare int, ma non il puntatore.

int const * i; 

è un const puntatore non ad un constint. È possibile modificare il puntatore ma non lo int.


Ora, per unique_ptr, è una questione di se l'const va all'interno o all'esterno della <>. Quindi:

std::unique_ptr<int> const u; 

è come il primo. È possibile modificare int, ma non il puntatore.

Quello che vuoi è:

std::unique_ptr<int const> u; 

È possibile modificare il puntatore, ma non il int. O forse anche:

std::unique_ptr<int const> const u; 

Qui non si può cambiare il puntatore o il int.


Notate come ho sempre posto il const a destra? Questo è un po 'raro, ma è necessario quando si tratta di puntatori. Lo const si applica sempre alla cosa immediatamente alla sua sinistra, ovvero * (il puntatore è const) o int. Vedi http://kuhllib.com/2012/01/17/continental-const-placement/.

scrittura const int, potrebbe condurvi a pensare int const * è un const -pointer ad un non constint, che è sbagliato.

7

Questo replica la semantica dei puntatori tradizionali. Un puntatore const è un puntatore che non può essere mutato. Tuttavia, l'oggetto che punta a può.

struct bar { 
    void do_bar() {} 
}; 

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

Per evitare mutando il pointee, è necessario l'equivalente di unique_ptr puntatore const a const o

const std::unique_ptr<const bar> b; 
Problemi correlati