让我们考虑以下代码(现场: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
等等......我知道这些,以及它这不是问题的关键,这不是生产代码。
答案 0 :(得分:4)
您使用的重载是:operator>>(std::istream&, char*)
。按值计算需要char*
。它不会修改指针(即它不会将指针改为指向其他地方的指针)。它修改指针保存地址的数据,将空终止的c-string写入该位置。因此,您的对象的常量不会被违反,因为该数据不是您对象的一部分。
如果您尝试执行以下操作:
a.a = NULL;
修改对象的成员,因此不允许。
其次这会导致未定义的行为吗?
如果a.a
没有指向正确分配的内存,并且有足够的空间用于流中的下一个空格分隔的char数据,那么它可以。但不是因为与StrStrTest
对象的常量有任何关系。