C++ 如何保持typedef'的常量;d型

C++ 如何保持typedef'的常量;d型,c++,C++,每隔一段时间,我就会被这件事弄得心烦意乱,没有人能给出令人满意的答案 在这样一个(公认是人为的)例子中 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;
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;
}
。。。警察被扔了。非成本方法可以在
m_str
上调用,也可以重新分配,这是误导性的,因为它旁边写着
const

  • 第二个例子可以纠正以保持恒定吗
  • 哪里/为什么C++规范表明这是正确的行为?< /LI>
  • 最佳实践对此有何看法

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

      const std::string &
      
      应理解为“对常量字符串的引用”(但不是“对字符串的常量引用”)

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

      这或多或少类似于这个问题:指向常量字符串的指针确保不修改指针后面的字符串。指向非常量字符串的常量指针可确保不重新定位指针(引用不可能实现这一点,因此当我们说“常量引用”时,我们总是指第一种情况!)

      简单地说,在对引用进行类型别名时,必须先考虑常量,而不是以后(顺便说一下,指针也是如此)。因此,需要另一个typedef来引用常量字符串,如下所示:

      typedef const std::string &_strcref;
      
      常量被“删除”,因为您没有对常量字符串的引用,您有对非常量字符串的常量引用,常量引用没有任何意义,引用无论如何都不能重新绑定,它们只绑定到一个对象一次,并保持这种状态

      i、 e.你的

      const _strref m_str;
      
      不是

      const string& m_str;
      
      而是

      string& const m_str;
      
      这种类型没有意义,所以
      const
      会被删除,它只是

      string& m_str;
      
      换句话说,您不能在typedef中“插入”const。typedef是
      字符串&
      ,是对
      字符串的引用
      ,您不能通过将
      常量
      放在其前面,将其更改为对其他类型(常量字符串)的引用。。。无法更改引用所引用对象的类型


      正如其中一条评论所指出的,最好的解决方案是不要将typedef用作引用,这对您毫无益处。如果您使用
      \u str&
      而不是
      \u stref
      ,那么您可以毫无问题地添加
      常量
      ,例如
      常量&
      \u str const&
      ,问题的核心是typedef在类型定义中引入了类似于“括号”的内容,用于限定符,如
      常量

      也就是说,
      const std::string&
      表示:

      将引用应用于类型a,即
      const
      应用于类型B,即
      std::string

      但是,
      const\u stref
      表示:

      const
      应用于类型a,即
      \u stref
      ,它是对
      std::string
      的引用

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

      如果您真的想使用这样的typedef,您必须将
      常量
      放入typedef中:

      typedef const std::string & _cstrref;
      

      然而,我认为引用typedef(在较小程度上,指针typedef也是如此)会恶化程序的可读性。当我看到一个参数前面没有
      &
      的函数声明时,我希望会出现按值传递。

      那么
      typedef const std::string&\u strref?请注意:我不会键入def引用和指针。没有真正的好处,它隐藏了信息。您只需键入一个字符,在您的示例中,您甚至可以键入更多字符-