“std :: string const& s”和“const std :: string& s”之间有什么区别?

时间:2016-03-10 09:57:12

标签: c++ c++11 reference const

我一直在寻找有关如何做某事的例子,并看到了这两个变种:

std::string const &s;
const std::string &s;

在不同的片段中。

你的回答:)

5 个答案:

答案 0 :(得分:8)

std::string const &相当于const std::string &

const std::string &是Stroustrup的 The C ++ Programming Language 中采用的风格,可能是“传统风格”。

std::string const &可以比替代方案更加一致:

  

const-on-the-right风格总是将const放在它所支配的权利的右边,而另一种风格有时将const放在左边,有时放在右边。 / p>      

使用const-on-the-right样式,const的局部变量用右边的const定义:int const a = 42;。类似地,const的静态变量定义为static double const x = 3.14;。基本上每个const都会出现在它所支持的事物的右边,包括需要在右边的const:使用const成员函数。

(有关详细信息,请参阅What do “X const& x” and “X const* p” mean?。)

如果你决定使用const-on-the-right风格,请确保不要错误输入std::string const &s作为荒谬的std::string & const s

以上声明表示:“s是对const”的std::string引用。 这是多余的,因为引用始终是const(您永远不能重置引用以使其引用不同的对象)。

答案 1 :(得分:5)

技术上它是相同的,没有任何区别。但是在一些调试器中(肯定是lldb),即使你写成std::string const&,你也会看到const std::string&

答案 2 :(得分:2)

只是为了证明其他人的断言(我理解rtti不会将{const}或voltilness带入.name()输出中)

这个测试程序:

 #include <string>
 #include <iostream>

 using std::string;
 using std::cout;
 using std::cin;

  using std::endl;

  int main()
  {
    std::string t = "BLABLA" ;
    std::string t1 = "BLABLA" ;
    std::string const &s = t;
    const std::string &d = t1;


if (typeid(d) == typeid(s)) 
    cout << "d and s are the same type according to the rtti" << endl;

else
    cout << "d and s are the NOT the same type according to the rtti" <<  endl;
    // here the raw output is exactly the same for both
    cout << typeid(d).raw_name() << endl << typeid(s).raw_name() << endl; 

    cin >> t;
    return 0;
}

对于gcc(4.9.2)(经适当修改)msdn(vs2010)为两者返回“相同类型”。

我将这个“答案”作为一种贡献,而不是作为“答案”。

编辑:阅读Scott-Meyers的“Effective Modern C ++”中的第4项,分享了一些关于我写的例子的非常有趣的隐藏信息。 简而言之,因为我们按值传递变量名,所以typeid不会产生可靠的结果。 当我们通过值传递方法变量时,推导出的类型会失去其常数,波动性和参考性(因为上帝的爱将缩短为cvr)。这就是为什么上面的例子不能证明两种类型之间是否存在差异。

同一个Item声明Boost项目托管了一个名为TypeIndex的库,它保留了cvr属性。

答案 3 :(得分:2)

如上所述,它们属于同一类型。喜欢右侧const的一个原因是它如何与模板一起使用。大多数人只是通过替换处理功能模板。例如:

template <class T> void foo(const T& arg);

int* p;
foo(p);

arg的类型是什么?您想说const int*&,也就是说,指向const int的指针,但错误。文字替换失败了。如果你写了它而不是像

那样
template <class T> void foo(T const& arg);

然后简单的文本替换产生正确的类型:int* const&。也就是说,const指向int的引用。

答案 4 :(得分:2)

正如Barry所指出的那样in his answer旧的C语法(以及该语法的C ++扩展)并不支持文本替换的概念视图,就像在数学中一样。

直接使用C语法因此通常最好编写T const,而不是const T,即使T是一个简单类型,这些类型表达式< EM>等效。编写T const还可以避免像char const* const p;这样的多级指针声明中的不一致,其中最后const无法移动。这表明等价仅适用于声明开头的基类型。

几个月前,我开始编写const T的实验,并使用该符号始终。因为现在可以在C ++ 11之后使用,而不使用宏。为了支持一致性,我使用了名为类型构建器

template< class Some_type >
using Ptr_ = Some_type*;

这样,而不是从右到左读取

char const* const p = something;

我可以并且确实写了普通的阅读方向

const Ptr_<const char> p = something;

它有点冗长,但我现在,凭借一些使用它的经验,认为它是值得的(我不确定,这是一个实验)。

主要缺点是虽然这种表示法支持(函数模板)函数参数的类型推导,就像直接使用C语法一样,但它不支持auto声明的类型推导。令人高兴的是,由于可以轻松地创建初始化程序const,所以关于唯一有问题的情况是对数组的引用。到目前为止我的实用解决方案是在这种情况下直接使用C(或更确切地说,C ++)语法,但我认为这代表了语言的缺点或漏洞,可能还有一些通用的解决方案可以使事情变得更容易其他情况。

对于我当前的Ptr_类型构建器,请参阅the cppx/core_language_support/type_builders.hpp file at Github。它们包括例如In_用于函数参数。是的,我发现,尽管有些冗长,但在清晰度方面也值得,因为它使意图非常明确。但是,cppx的东西是实验性的,可能会发生变化。链接到这里的特定文件甚至可以移动,但它将在那里。 :)