3

每隔一段时间我就会被这个挂断,没有人真正能够给出令人满意的答案。

在这样的(诚然人为的)例子中......

typedef std::string _str;
class MyClass
{
public:
    MyClass(const _str &s) : m_str(s) { }
private:
    const _str &m_str;
}

... 事情和预期的差不多。该成员m_str只能在构造函数初始化器列表中分配,以后不能重新分配,并且非常量迭代器不可用。好吧。但如果我们这样做...

typedef std::string _str;
typedef std::string &_strref;
class MyClass
{
public:
    MyClass(const _strref s) : m_str(s) { }
    void test() { m_str.append(std::string("why am I not const?")); }
private:
    const _strref m_str;
}

... const 被删除。非成本方法可能会被调用m_str并且可能会被重新分配,考虑到它已经const写在它旁边,这是一种误导。

  • 可以更正第二个示例以保持 const-ness 吗?
  • c++ 规范在哪里/为什么表明这是正确的行为?
  • 最佳实践对此有什么看法?
4

3 回答 3

7

问题是我们所说的“常量引用”。这有点令人困惑。应该是 const 的不是引用,而是引用的对象:

const std::string &

应该读作“对 const 字符串的引用”(而不是“对字符串的 const 引用”)。

您为字符串引用定义了类型别名。然后,您实例化了对此类的 const 引用。但是引用总是常量,所以你的const被忽略了。此引用所引用的字符串不是const。

它或多或少类似于这个问题:指向 const-string 的指针确保您不会修改指针后面的字符串。指向非 const 字符串的 const 指针确保您不会重新定位指针(这在引用中是不可能的,所以当我们说“const 引用”时,我们总是指第一种情况!)

所以简而言之:当对引用进行类型别名时,您必须已经关心常量,而不是以后(顺便说一句,指针也是如此)。因此,您需要另一个 typedef 来引用 const 字符串,如下所示:

typedef const std::string &_strcref;
于 2013-05-11T10:11:48.443 回答
4

const 被“删除”是因为你没有对 const 字符串的引用,你有对非 const 字符串的 const 引用,而 const 引用是没有意义的,无论如何都不能重新绑定引用,他们' 绑定到单个对象一次并保持这种状态。

即你的

const _strref m_str;

不是

const string& m_str;

反而

string& const m_str;

并且那种类型没有意义,所以const被丢弃了,它只是

string& m_str;

换句话说,您不能“插入” consttypedef 的“内部”。typedef 是string&对 a 的引用string,您不能通过将其更改为对不同类型 (a const string)的引用const...不能更改引用所指对象的类型。

正如其中一条评论所指出的,最好的解决方案是不要将 typedef 用于引用,它不会为您带来任何好处。如果你使用_str&代替_strrefthen 你可以const毫无问题地添加,作为const _str&或者_str const&

于 2013-05-11T10:12:47.337 回答
4

问题的核心是 typedef 在类型定义中引入了诸如const.

也就是说,const std::string &意味着:

将引用应用于类型 A,该类型const应用于类型 B,即std::string.

然而,const _strref意味着:

应用于const类型 A,即_strref,它是对 的引用std::string

换句话说,非 typedef 版本给出了对常量字符串的引用,而 typedef 版本产生了对可变字符串的“常量”引用。由于引用本身不能是常量或非常量,因此const简单地删除了。

如果你真的想使用这样的 typedef,你必须将 放入consttypedef 中:

typedef const std::string & _cstrref;

但是,我认为引用 typedef(在较小程度上还有指针 typedef)会降低程序的可读性。当我看到一个没有&参数前面的函数声明时,我预计会发生按值传递。

于 2013-05-11T10:15:32.870 回答