2014-11-24 15 views
1

讓我們看看下面的代碼(在直播:http://ideone.com/3Ky4Krconst的行爲>>

#include <iostream> 
#include <string> 
#include <cstdlib> 
#include <cstring> 

class StrStrTest { 
public: 
    StrStrTest(const std::string& ba) { 
     a = (char*)calloc(1, ba.length() + 1); 
     strcpy(a, ba.c_str()); 
    } 
    virtual ~StrStrTest() { 
     free(a); 
    } 
private: 
    char* a; 
    friend std::basic_ostream<char>& operator << (std::basic_ostream<char>& ss, const StrStrTest& a); 
    friend std::basic_istream<char>& operator >> (std::basic_istream<char>& ss,const StrStrTest& a); 
}; 
std::basic_ostream<char>& operator << (std::basic_ostream<char>& ss, const StrStrTest& a) { 
    ss << a.a; 
    return ss; 
} 
std::basic_istream<char>& operator >> (std::basic_istream<char>& ss, 
             const StrStrTest& a) { 
    ss >> a.a; // <<-- HERE 
// a.a = NULL; 
    return ss; 
} 
int main() 
{ 
    StrStrTest bb("foo"); 
    std::cin >> bb; 
    std::cout << bb; 
} 

首先,爲什麼它編譯?在標有< < - HERE的行上(巧妙地)修改const對象。 (顯然a.a = NULL;不能編譯,這太明顯了)。

其次,這是否會導致未定義的行爲? PS:請不要認爲代碼不安全,可能會覆蓋它不擁有的內存,char*std::string等等......我知道這些,這不是問題的關鍵,不是生產代碼。

+0

您修改的內存分配在堆上,恰巧也是由const對象指向的。 – 2014-11-24 10:53:40

回答

4

您使用的超負荷是:operator>>(std::istream&, char*)。按價值計算,需要char*。它不會修改指針(即不會將指針更改爲指向其他地方)。它修改指針保存地址的數據,寫一個空終止的c字符串到那個位置。所以,你的對象的一致性沒有被侵犯,因爲這些數據不是你的對象的一部分。

如果你試圖做這樣的事情:

a.a = NULL; 

修改你的對象的成員,因此是不允許的。

其次是否會導致未定義的行爲?

它可以,如果a.a沒有指向正確分配的內存有足夠的空間用於流中下一個空格分隔的char數據。但並不是因爲與對象的常量有關。

相關問題