2013-04-22 69 views
4

我有一些代碼已經被寫入而不考慮const的正確性。有沒有在改變這個添加const正確性

class X 
{ 
public: 
    X(X& rhs); // does not modify rhs 
    ... 
}; 

這個

class X 
{ 
public: 
    X(const X& rhs); 
    ... 
}; 

將改變現有的程序的行爲的情況?我知道這種改變會允許當前沒有編譯的代碼進行編譯,但是如果有任何已編譯的代碼會改變它的行爲的情況,我很感興趣。

類似的問題,是否有任何優點,而不是改變?

class X 
{ 
public: 
    X(X& rhs); // does not modify rhs 
    X(const X& rhs); 
    ... 
}; 
+0

我可以看到我的問題已被輕微誤解。我不問如何重寫複製構造函數,我的問題是在給定使用類X的大量代碼時是否存在任何危險。此代碼是由完全不知道const並且正在使用編譯器不關心。現在在移植到一個新的編譯器時,我剩下的代碼不能編譯,並且我不能在STL中使用類。 – john 2013-04-22 17:15:55

回答

2

對於複製構造函數我不這麼認爲。但請注意,一般來說,是的,const的聲明可以影響調用哪個方法。唯一想到的例子是數組重載 - 參見例如this question

0

由於您正在更改具有複製構造函數的類,我假設您可以檢查複製構造函數代碼。如果你可以做這個改變,並且複製構造函數不會給出編譯器錯誤,那麼你可能是好的。要考慮的一個案例是複製賦值操作符,因爲沒有保證,特別是在優化的代碼中會被調用。所以也要確保你的拷貝分配可以使用一個const參數。

+1

您可以舉一個例子,您不能確定是否會調用複製構造函數或賦值運算符? – Agentlien 2013-04-22 12:46:30

+0

這是來自我問過的一個問題。 http://stackoverflow.com/questions/9267687/understanding-eliding-rules-with-regard-to-c11 – rerun 2013-04-22 12:48:06

+0

據我所知,這隻意味着你不能確定副本是否會被刪除。無論如何,當您(有理由)期望複製構造函數時,我不會看到賦值運算符會被調用的情況,反之亦然。 – Agentlien 2013-04-22 12:52:32

1

事實上,複製構造函數應該,imho,總是以const引用作爲參數。

X(X& rhs) { } // does not modify rhs 

這不允許複製常量對象,因此下面的代碼不會編譯。 雖然非const對象可以作爲常量參數,倒過來是不可能的

X const test; 
X new_x(test); 

我不能想象爲什麼有人要排除一個const對象的副本。

關於您想要進行的更改: 複製構造函數是否依賴於非const定義的任何X成員函數?

這工作就像一個魅力,但允許複印const對象:

class X 
{ 
private: 
    int a; 
public: 
    X(X &rhs) { a = rhs.value(); } 
    int& value (void) { return a; } 
}; 

下一個示例將無法編譯,因爲rhs是常量,但value()不是常量。

class X 
{ 
private: 
    int a; 
public: 
    X(X const &rhs) { a = rhs.value(); } 
    int& value (void) { return a; } 
}; 

如果你想讓你的類的常量正確,你可能需要檢查整個類。 它應該只會影響您的課堂實施。因爲我不知道外部代碼應該依賴於類成員函數的「非常量」的情況。 除非我的例子中的任何公共成員函數返回非const引用。

以下代碼片段將按照預期執行。

class X 
{ 
private: 
    int a; 
public: 
    X(int const &b) : a(b) { } 
    X(X const &rhs) { a = rhs.value(); } 
    int const & value (void) const { return a; } 
}; 

但要知道,這將像任何干擾代碼:

X test(100); 
test.value() = 12; 

此使用int& value (void) { return a; }會工作,但失敗int const & value (void) const { return a; }。 你當然可以提供兩個安全的方面。

0

djechlin在his answer作出重要的一點,雖然有點不清楚,所以我會盡力解釋更好。

對象或引用的常量影響重載解析。舉例來說,如果你有一個成員函數的const基於超載的對象,不同的重載將被選擇:現在

struct foo { 
    void do_stuff(); 
    void do_stuff() const; 
}; 

int main() { 
    foo f; 
    const foo& fr = f; 

    f.do_stuff(); // calls non-const version 
    fr.do_stuff(); // calls const version 
} 

,如果重載之一,具有副作用,其他沒有,你」 d改變簽名後會得到不同的行爲,假設(或者,即使)程序編譯得很好。