我找不到關於const_cast
的很多信息。我可以找到的唯一信息(堆棧溢出)是:const_cast是否安全?
const_cast<>()
用於添加/刪除變量的const(ness)(或volatile- ness)。
這讓我很緊張。可以使用const_cast
會導致意外的行爲?如果是這樣,什麼?
另外,什麼時候可以使用const_cast
?
我找不到關於const_cast
的很多信息。我可以找到的唯一信息(堆棧溢出)是:const_cast是否安全?
const_cast<>()
用於添加/刪除變量的const(ness)(或volatile- ness)。
這讓我很緊張。可以使用const_cast
會導致意外的行爲?如果是這樣,什麼?
另外,什麼時候可以使用const_cast
?
const_cast
只有在您投射最初爲非const
的變量時纔是安全的。例如,如果您有一個功能需要const char *
的參數,並且您傳遞了可修改的char *
,則可以安全地將該參數返回到char *
並對其進行修改。但是,如果原始變量實際上是const
,則使用const_cast
將導致未定義的行爲。
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
這不是真的。 C++標準。 5.1.1節說除了任何聲明mutable的類成員(7.1.1)都可以被修改以外,任何在其生命週期(3.8)修改const對象的嘗試都會導致未定義的行爲**任何嘗試**!沒有關於原始變量的文字。 – 2010-11-08 15:12:56
@Alexey:原始變量是關於指向或引用的內容。您可以對非const對象採用const引用,因此將其轉換爲可寫引用是明確定義的行爲,因爲所引用的對象實際上並不是const。 – Puppy 2010-11-09 16:53:29
@DeadMG:`你可以對非const對象進行const引用。就這樣。之後,你有一些const對象而不是非const對象。此外,有些情況下允許創建一個初始非const對象的const副本。例如,對於函數參數的情況。 – 2010-11-12 10:23:28
我覺得很難相信,這是你能找到的const_cast的只有信息。從second Google hit報價:
如果丟掉一個 對象的常量性已經明確 聲明爲const,並嘗試 修改它,結果是不確定的。
不過,如果你丟掉了 常量性尚未 明確聲明爲const對象的,你 可以安全地修改它。
如果您開始修改編譯器認爲是const的東西,那麼您正在破壞線程安全的任何機會。
亞當說什麼。另一個例子,其中的const_cast會有所幫助:
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;
};
我們先加一個const,以種類this
點,那麼我們稱之爲getT
const版本,然後我們從返回類型,這是有效的,因爲t
刪除常量必須是非const的(否則,不可能調用getT
的非const版本)。如果你有一個大的函數體,並且你想避免冗餘代碼,這可能非常有用。
我可以想到const_cast是安全和有用的兩種情況(可能有其他有效的情況)。
一個是當你有一個常量實例,引用或指針,並且你想傳遞一個指針或引用到一個不是常量正確的API,但是你不會修改該對象。你可以const_cast指針並將它傳遞給API,相信它不會真的改變任何東西。例如:
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()));
}
另一種是如果你使用的是沒有實現「可變」舊的編譯器,你想創建一個類,在邏輯上是常量,但不按位常量。你可以在const方法中const_cast'this'並修改你的類的成員。
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];
}
};
簡短的回答是否定的,這是不安全的。
長的答案是,如果你知道足夠使用它,那麼它應該是安全的。
當你投射時,你基本上說的是「我知道編譯器不知道的東西。」在const_cast的情況下,你所說的是「即使這個方法需要一個非const引用或指針,我知道它不會改變我傳遞它的參數。」
所以如果你確實知道你在使用演員時聲稱知道什麼,那麼使用它就可以。
#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;
}
頂端回答忽視的東西,可能是可怕的,但顯而易見的是值得指出:它只是變得不安全_if試圖修改原來`const` object_經過一個去`const` -ed引用/指針。相反,如果你只是`const_cast`來解決一個糟糕的(或者,在我的情況下是懶惰的)spec'd API,它只接受一個非``const`引用,但只會在`const`方法中使用...沒有任何問題。 – 2015-12-22 01:39:30