运算符中的Const行为>>

时间:2014-11-24 10:46:31

标签: c++ const

让我们考虑以下代码(现场:http://ideone.com/3Ky4Kr

#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;
}

首先,为什么要编译?在标有&lt;&lt; - HERE 的行上(巧妙地)修改const对象。 (显然a.a = NULL;没有编译,这太明显了。)

其次这会导致未定义的行为吗?

PS:请不要认为代码不安全,可能会覆盖它不拥有的内存,char*std::string等等......我知道这些,以及它这不是问题的关键,这不是生产代码。

1 个答案:

答案 0 :(得分:4)

您使用的重载是:operator>>(std::istream&, char*)。按值计算需要char*。它不会修改指针(即它不会将指针改为指向其他地方的指针)。它修改指针保存地址的数据,将空终止的c-string写入该位置。因此,您的对象的常量不会被违反,因为该数据不是您对象的一部分。

如果您尝试执行以下操作:

a.a = NULL;

修改对象的成员,因此不允许。

  

其次这会导致未定义的行为吗?

如果a.a没有指向正确分配的内存,并且有足够的空间用于流中的下一个空格分隔的char数据,那么它可以。但不是因为与StrStrTest对象的常量有任何关系。