如何保持typedef类型的常量

时间:2013-05-11 10:07:36

标签: c++

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

在这样一个(公认的做作)例子......

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

......事情的效果与预期的一样。成员m_str只能在构造函数初始化列表中分配,以后不能重新分配,非const迭代器不可用。好吧。但是,如果我们这样做......

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

  • 第二个例子可以更正以维持常量吗?
  • c ++规范在哪里/为什么表明这是正确的行为?
  • 最佳做法对此事有何看法?

3 个答案:

答案 0 :(得分:6)

问题是我们通过说“const reference”理解的。这有点令人困惑。它不是应该是const的引用,而是引用的对象:

const std::string &

应该被理解为“对const字符串的引用”(但不是“对字符串的const引用”)。

您为字符串引用定义了一个类型别名。然后,您实例化了一个const引用。但引用始终是const,因此忽略const此引用引用的字符串不是 const。

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

所以简而言之:当引用类型别名时你必须关注const-ness,而不是更晚(顺便说一下,指针也是如此)。因此,您需要另一个typedef来引用const字符串,如下所示:

typedef const std::string &_strcref;

答案 1 :(得分:4)

const被“删除”,因为你没有对const字符串的引用,你有一个对非const字符串的const引用,而const-reference是没有意义的,引用永远不会被重新绑定无论如何,他们只能绑定一个物体并保持这种状态。

即。你的

const _strref m_str;

不是

const string& m_str;

而是

string& const m_str;

并且该类型没有意义,因此const被删除而且只是

string& m_str;

换句话说,你不能在typedef中“插入”const“。 typedef为string&,是对string的引用,您不能将const string添加到其中,以将其更改为对其他类型(const)的引用......不能改变引用引用的对象类型。

正如其中一条评论所指出的那样,最佳解决方案是不使用typedef作为引用,它什么也得不到。如果您使用_str&代替_strref,那么您可以constconst _str&

添加_str const&而不会出现任何问题

答案 2 :(得分:4)

问题的核心是,typedef引入了类似"括号"关于限定词的类型定义,例如const

const std::string &表示:

对类型A应用引用,const应用于类型B,即std::string

但是,const _strref表示:

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

换句话说,非typedef版本提供对常量字符串的引用,而typedef版本产生一个"常量"引用可变字符串。由于引用本身不能是常量或非常量,const只会被删除。

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

typedef const std::string & _cstrref;

但是,我认为引用typedef(以及较小程度的指针typedef)会恶化程序的可读性。当我在参数前看到没有&的函数声明时,我希望按值传递。