2015-02-18 12 views
6

Poniższy kod pozwala mi zmienić wartość na * p2, mimo że p2 jest zadeklarowane przy const.Używanie const i decltype ze zmienną wskaźnika

int *p1; 

const decltype(p1) p2 = new int(100); 
*p2 = 200; 
cout << "*p2: " << *p2 << endl; // Outputs *p2: 200 

Jednak jeśli użyję "int *" zamiast "decltype (p1)", kompilator zgłosi błąd.

const int * p2 = new int(100); 
*p2 = 200; 
cout << "*p2: " << *p2 << endl; 

error: assignment of read-only location ‘* p2’ 
    *p2 = 200; 
    ^

Używam g ++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2.

Czy decltype zignoruje specyfikator const, gdy zostanie zastosowany do zmiennej wskaźnika?

Odpowiedz

10

const decltype(p1) p2 oznacza int* const p2.

Oznacza to, że nie można zmienić p2, ale można zmienić wskazane rzeczy.


const T zawsze stosuje const do tak zwanego "najwyższym poziomie" z T. Gdy T jest typem złożonym (to jest typ zbudowany z podstawowego zestawu typów), musisz przeskoczyć przez obręcze, jeśli chcesz zastosować const na niższych poziomach.

Gdy T jest int *, dodanie stałego poziomu najwyższego dałoby int * const. The * wyznacza poziom; aby uzyskać dostęp do rzeczy poniżej *, musisz ręcznie usunąć *, zastosować const, a następnie odłożyć *.

Możliwym rozwiązaniem jest:

const std::remove_pointer<decltype(p1)>::type *p2 = new int(100); 
+0

@ Quantdev masz rację, skopiowałem z innej odpowiedzi SO bez testowania. Czy istnieje inne rozwiązanie? –

+0

Nie wiem, interesujący problem .. – quantdev

+0

@quantdev Istnieje "const std :: remove_reference :: type * p2 = ...;' chociaż jest to nieco brzydkie –

4

std::pointer_traits by się przydał tutaj. std::pointer_traits::element_type i std::pointer_traits::rebind pozwalają napisać wyrażenie ogólne, które będzie działać dobrze dla każdego rodzaju wskaźnik podobny:

using element_type = std::pointer_traits<decltype(p1)>::element_type; 
using pointer_like_to_const = std::pointer_traits<decltype(p1)>::rebind<std::add_const_t<element_type>>; 
pointer_like_to_const p2 = new int(100); 

Zauważ, że ten kod będzie działać, nawet jeśli p1 był shared_ptr<int> lub unique_ptr<int>.

Powiązane problemy