运算符>>中的常量行为

Const behavior in operator >>

本文关键字:gt 常量 运算符      更新时间:2023-10-16

让我们考虑以下代码(实时: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;
}

首先,为什么要编译?在标有 <<的行上——这里我(巧妙地)修改了一个const对象。(显然a.a = NULL;不编译,这太明显了)。

其次,这是否会导致未定义的行为?

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

您使用的重载是这样的:operator>>(std::istream&, char*) .它需要char*,按值。它不会修改指针(即它不会将指针更改为指向其他地方)。它修改指针保存其地址的数据,将一个以空结尾的 c 字符串写入该位置。因此,对象的恒定性没有被违反,因为该数据不是对象的一部分。

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

a.a = NULL;

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

其次,这是否会导致未定义的行为?

如果a.a没有指向正确分配的内存,并且有足够的空间用于流中的下一个空格分隔的字符数据,则可以。但不是与StrStrTest对象的恒定性有关的任何结果。