2010-08-06 112 views
2

我通常在C/C++代碼中使用C類型鑄造。我的問題是,在轉換類型中添加「const」關鍵字對結果意味着什麼?用「const」關鍵字C類型鑄造

例如,我能想起來的幾個場景:

const my_struct *func1() 
{ 
    my_struct *my_ptr = new my_struct; 

    // modify member variables 

    return (const my_struct *)my_ptr; 
    // return my_instance; 
} 

在這其中,功能構建一個結構的新實例,並鑄造一個常量指針,因此調用者就不能進一步修改其內部狀態,但刪除它。是否需要「推薦」或者根本不需要「const」轉換,因爲任何return語句都可以工作。

在這一個中,my_basemy_derive的基類。

const my_base *func2(const my_derive *my_ptr) 
{ 
    return (const my_base *)my_ptr; 
    // return (my_base *)my_ptr; 
} 

由於my_ptr已經是一個常量指針,將與(my_base *)鑄造它涉及對返回時,取出常量和另一個隱含的const_cast const_cast類型轉換?

是否有任何理由將「const」添加到整數函數參數,因爲更改它永遠不會影響函數外部的狀態?

void func3(const int i) 
{ 
    // i = 0; is not allowed, but why, as it is harmless? 
} 

如何在投射整數時加入「const」?我認爲這應該類似於func2()

void func4(short i) 
{ 
    const unsigned int j = (const unsigned int) i; 
    // const unsigned int j = (unsigned int) i; 
} 

糾正我,如果我錯了。考慮到類型轉換可能是一個常見問題解答,我不確定這個問題是否與其他問題重複。謝謝!

+2

這個問題提到了「C/C++」,這是一個壞主意。特別是在這裏,因爲雖然C和C++都有一個「const」關鍵字,但它的含義卻非常不同。 – Gilles 2010-08-06 18:34:07

回答

6

在鑄造類型中添加const關鍵字意味着結果將保持不變。下面將不是在C++編譯(在C它沒有任何效果):

int* x = (const int*)malloc(10); // cannot convert from 'const int *' to 'int *' 

你真的不應該在你的C++代碼用C型鑄造。這是不安全的,應該只用於與傳統C代碼的兼容性。您應該使用C++強制轉換。

func3的情況下,通常const限定符未被使用。如果函數參數沒有指針或沒有引用類型,那麼將const限定符添加到函數參數沒有什麼大的理由。考慮以下幾點:

void func3(  TYPE i); // no reason to use `const` 
void func3(const TYPE& i); // use `const`, so as not to accidentally change `i` 

當您指定左值到右值,如func4,沒有必要明確指定中投表達const預選賽。左值到右值的轉換將根據C++標準4.1隱式執行。

+0

'malloc'示例很有趣。相反,即使在C++中也是如此:'int a = 0; int b =(const int)a;'我知道在C++中使用C cast是不安全的。我提出這個問題只是在理論上討論C鑄造的正確用法。我總是使用const引用來最小化參數傳遞成本並避免NULL指針。我可以理解,分配發生時可能存在隱式轉換。如果我錯過括號中的「const」,是否會產生額外的成本? 謝謝! – 2010-08-06 08:04:01

+0

編譯時間或...的額外成本? – 2010-08-06 08:24:24

+0

因此,C型鑄造沒有運行時間成本,對吧? – 2010-08-06 16:41:41

1

在第一個例子中,在需要const的函數中返回non-const會再次捕獲它,這意味着const是重要的,但是你不能注意到它,因爲如果它不存在,它將被添加。
在第二個例子中,它將會保持常量。
在第三個例子中,它是不允許的,因爲它是無害的:我會改變其餘的功能和不可恢復。
請記住,將類型放入不是它的類型的容器中將自動調用自動放置與int放在長字段中相同將不會保持int。
你還必須記住,const意味着與私有或公開的彙編程序相同,這不算什麼。生成的彙編程序代碼完全不會有差別,無論您將const放在哪裏,都將以相同的速度運行。

+0

你的意思是在鑄造時明確寫出「const」以最大限度地降低成本更好嗎?對於函數參數之一,正如*安東尼*所提到的,是否將「const」放在函數實現者的關注中,因此我認爲額外的「const」在使用外部庫時不會造成問題。謝謝! – 2010-08-06 08:12:35

+0

沒有什麼可以最小化的,除非投射操作符,否則投射什麼也不做。所有的鑄造都是在編譯時進行的,以保證類型安全。只有像int那樣的將double或char *轉換爲std :: string需要時間,即使在繼承中投射也不會執行任何操作。這完全是爲了類型安全,並且不會生成彙編代碼。 – Dani 2010-08-06 19:36:17

5

const添加到演員表就像將const添加到任何其他類型說明符---結果對象是const。這意味着什麼取決於上下文。如果您在頂層添加const(例如,const intconst fooint* const,那麼您只有const對象。在大多數情況下,可以複製和分配對象,就像非const對象一樣(儘管有一些例外,如std::auto_ptr )。

如果添加const一個指針,那麼你也可以將其添加到被指向的類型。例如int * constconst指針到一個純int,而const int*int const*是一個普通的指針const int

int i; 
int* p = (int* const) &i; // fine; top-level const not a problem 
int* p2 = (int const*) &i; // error; pointed-to object is const, so this is preserved 
int const* p3= (int const*) &i; // OK 

const參數聲明中的頂層與聲明任何其他局部變量const ---不能修改函數體內的命名對象。但是,const不構成函數類型的一部分,所以您可以在沒有(至少符合編譯器的情況下)前向聲明該函數。

void func(int i); // forward-declare func 
void func(const int i) // this matches the declaration 
{ 
    // i is const here 
} 

這可以說是良好的作風---變量是否被視爲const裏面的功能是實現細節,因此不應該在原型。在定義中,如果您不打算修改它,則遵循聲明const的指導原則。

使用const參數聲明別處(例如,作爲指針的一部分)會影響函數類型,如石膏。