为啥即使对于“写入时复制”的 const 成员函数也返回代理类?

Posted

技术标签:

【中文标题】为啥即使对于“写入时复制”的 const 成员函数也返回代理类?【英文标题】:Why return a proxy class even for const member function for "copy on write"?为什么即使对于“写入时复制”的 const 成员函数也返回代理类? 【发布时间】:2019-01-29 08:24:30 【问题描述】:

在More Effective C++中,给出如下代码

const String::CharProxy String::operator[] (int index) const

    return CharProxy(const_cast<String&>(*this), index);

String::CharProxy::operator char() const

    return theString.value->data[charIndex];

我们为什么不直接返回一个 char 而不是使用 const_cast 并稍后将 CharProxy 转换为 char?

【问题讨论】:

我想这样做的目的是允许获取一个指向底层字符的指针。 【参考方案1】:

如果我在你的情况下没有错的话,还有 non const 版本既可以读/写字符,也可以像 Real Fresh 所说的那样获取字符的指针/引用.

那么自然而然地为 const 版本提供相同的功能,允许读取字符(当然不是写入)并获取字符的指针/引用(常量)。

std::vector std::string

【讨论】:

所以即使其他人修改了字符串,我们仍然会得到更新的字符。但实际上,当有人通过非常量 CharProxy 修改它时,就会发生 String 的副本。也许重点是 const 和非常量运算符 [] 的统一接口。【参考方案2】:

这样做是为了使绑定到[] 的返回值的String::const_reference(即const String::CharProxy)不会在其他地方修改特定的String 时突然变得悬空。

您可以定义突变使所有引用无效,但这意味着您的 String 类将无法用于广泛的通用代码,并且是“远处的幽灵行动”。例如。你有代码 A 首先从 String 获取一个可变引用,然后代码 B 获取一个 const 引用,然后 A 通过它的引用发生变异。现在代码 B 的引用已经失效,它无法事先检查是否会发生这种情况。

注意,代理通过返回char,所以没有引用可以转义。

【讨论】:

这个更简单的解决方案似乎也可以,并且不存在悬空引用。 char String::operator[] (int index) const return value-&gt;data[index];

以上是关于为啥即使对于“写入时复制”的 const 成员函数也返回代理类?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 const 函数可以使用静态成员对象的非常量函数?

为啥这个 const auto 变量在 range-for 循环中为类的 const 成员函数编译?

为啥允许我从 const 成员函数调用 this->deviceContext->map() ?

const成员函数总结

类4(可变数据成员/基于const的重载)

为啥即使从类内部获取成员函数指针值也需要类名限定?