每隔一段时间我就会被这个挂断,没有人真的能给出满意的答案。
在这样一个(公认的做作)例子......
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
。
答案 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
,那么您可以const
或const _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)会恶化程序的可读性。当我在参数前看到没有&
的函数声明时,我希望按值传递。