Nie mogę znaleźć zbyt wielu informacji const_cast
. Jedyne informacje, które udało mi się znaleźć (na temat przepełnienia stosu) to:
const_cast<>()
Jest stosowany do dodawania / usuwania const (Ness) (lub lotny-ności) o zmiennej.
To mnie denerwuje. Czy użycie jakiegoś const_cast
powodu może spowodować nieoczekiwane zachowanie? Jeśli tak to co?
Ewentualnie, kiedy można go używać const_cast
?
c++
casting
const-cast
Mag Roader
źródło
źródło
const
obiekt za pomocąconst
usuniętego odniesienia / wskaźnika. Jeśli zamiast tego po prostuconst_cast
obejdziesz słabo (lub, w moim przypadku, leniwie) interfejs API, który akceptuje tylko brakconst
odniesienia, ale będzie używany tylko wconst
metodach ... nie ma żadnego problemu.Odpowiedzi:
const_cast
jest bezpieczny tylko wtedy, gdy rzutujesz zmienną, która pierwotnie była inna niżconst
. Na przykład, jeśli masz funkcję, która przyjmuje parametr aconst char *
i przekazujesz modyfikowalną wartośćchar *
, możesz bezpiecznieconst_cast
przywrócić ten parametr z powrotem do achar *
i zmodyfikować go. Jeśli jednak oryginalna zmienna była w rzeczywistościconst
, użycieconst_cast
spowoduje niezdefiniowane zachowanie.void func(const char *param, size_t sz, bool modify) { if(modify) strncpy(const_cast<char *>(param), sz, "new string"); printf("param: %s\n", param); } ... char buffer[16]; const char *unmodifiable = "string constant"; func(buffer, sizeof(buffer), true); // OK func(unmodifiable, strlen(unmodifiable), false); // OK func(unmodifiable, strlen(unmodifiable), true); // UNDEFINED BEHAVIOR
źródło
§7.1.5.1/4 says Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior
Każda próba ! Nie ma słów o oryginalnej zmiennej.const_cast
usuwaniaconst
czegoś, co zostało pierwotnie zadeklarowaneconst
. Ale to jest UB rzeczywiście spróbować napisać do tego obiektu. Dopóki tylko czytasz, wszystko jest w porządku iconst_cast
samo w sobie nie powoduje UB. To okropny pomysł, ale nie jest z natury UB.Przychodzą mi do głowy dwie sytuacje, w których const_cast jest bezpieczne i przydatne (mogą istnieć inne ważne przypadki).
Jeden z nich to sytuacja, w której masz instancję stałej, odwołanie lub wskaźnik i chcesz przekazać wskaźnik lub odwołanie do interfejsu API, który nie jest zgodny ze stałą stałą, ale jesteś PEWNY, że nie zmodyfikujesz obiektu. Możesz const_cast wskaźnik i przekazać go do API, ufając, że tak naprawdę niczego nie zmieni. Na przykład:
void log(char* text); // Won't change text -- just const-incorrect void my_func(const std::string& message) { log(const_cast<char*>(&message.c_str())); }
Druga to sytuacja, gdy używasz starszego kompilatora, który nie implementuje opcji „mutable” i chcesz utworzyć klasę, która jest logicznie stała, ale nie bitowa. Możesz const_cast „this” w ramach metody const i modyfikować członków swojej klasy.
class MyClass { char cached_data[10000]; // should be mutable bool cache_dirty; // should also be mutable public: char getData(int index) const { if (cache_dirty) { MyClass* thisptr = const_cast<MyClass*>(this); update_cache(thisptr->cached_data); } return cached_data[index]; } };
źródło
const_cast
może powodować nieokreślone zachowanie, a nie jakie są jego przydatne zastosowaniaconst_cast
jest prawidłową odpowiedzią. Nie mahe
pytań, ponieważ samo pytanie jest tematem.Trudno mi uwierzyć, że to jedyna informacja, jaką można znaleźć o const_cast. Cytując z drugiego hitu Google :
źródło
const_cast
. Lub wywołaj na nim metodę const.Co mówi Adam. Inny przykład, w którym const_cast może być pomocne:
struct sample { T& getT() { return const_cast<T&>(static_cast<const sample*>(this)->getT()); } const T& getT() const { /* possibly much code here */ return t; } T t; };
Najpierw dodajemy const do typu, na który
this
wskazuje typ , następnie wywołujemy wersję constgetT
, a następnie usuwamy const z typu zwracanego, który jest prawidłowy, ponieważt
musi być inny niż const (w przeciwnym razie wersja non-constgetT
nie mogłaby został wezwany). Może to być bardzo przydatne, jeśli masz dużą treść funkcji i chcesz uniknąć nadmiarowego kodu.źródło
const_cast
czystatic_cast
jest lepiej.const_cast
możesz robić tylko to, co chcesz: zmienić kwalifikatory CV.static_cast
może „po cichu” wykonywać inne operacje, których nie zamierzasz. Jednak pierwsza obsada jest całkowicie bezpieczna istatic_cast
zwykle jest bezpieczniejsza niżconst_cast
. Myślę, że jest to sytuacja, w którejconst_cast
lepiej komunikuje twoje zamiary, ale lepiejstatic_cast
komunikuje bezpieczeństwo twoich działań.Krótka odpowiedź brzmi: nie, to nie jest bezpieczne.
Długa odpowiedź jest taka, że jeśli wiesz wystarczająco dużo, aby go używać, powinno być bezpieczne.
Podczas przesyłania zasadniczo mówisz: „Wiem coś, czego kompilator nie wie”. W przypadku const_cast mówisz: „Nawet jeśli ta metoda przyjmuje odniesienie lub wskaźnik inne niż const, wiem, że nie zmieni parametru, który ją przekazuję”.
Więc jeśli naprawdę wiesz, co twierdzisz, że wiesz, używając obsady, możesz jej użyć.
źródło
Niszczysz wszelkie szanse na bezpieczeństwo wątków, jeśli zaczniesz modyfikować rzeczy, które kompilator uważał za const.
źródło
const
.const
to zaufanie.const_cast
łamie to zaufanie :(#include <iostream> using namespace std; void f(int* p) { cout << *p << endl; } int main(void) { const int a = 10; const int* b = &a; // Function f() expects int*, not const int* // f(b); int* c = const_cast<int*>(b); f(c); // Lvalue is const // *b = 20; // Undefined behavior // *c = 30; int a1 = 40; const int* b1 = &a1; int* c1 = const_cast<int*>(b1); // Integer a1, the object referred to by c1, has // not been declared const *c1 = 50; return 0; }
źródło: http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fkeyword_const_cast.htm
źródło