在C ++中使用const的正确方法是什么?

时间:2010-10-14 23:48:10

标签: c++ const const-correctness

const正确让我有点困惑。

你用什么经验法则决定什么时候应该是const?

e.g。考虑这个例子

class MyClass
{
  string ToString(); // this one?
  const string& ToString(); // or this? 
  const string& ToString() const; // or this?

  char* ToString(); // What about this?
  const char* ToString(); // or this?
  const char* ToString() const; // or this?
  const char const* ToString(); // Is this legal?
  const char const* ToString() const; // how about this?
  char const* ToString();  // or even this?
};

Const会让人感到困惑。

所有这些ToString方法之间有什么区别?

如果我理解正确,第一个返回一个可以修改的新字符串对象 如果需要的话。 第二个返回一个常量引用,也许它应该是字符串const& toString()方法。 第三个可能是废话,因为引用总是不变的是正确的吗?

以为我会在那里抛出旧的char *版本进行比较,因为我有返回对象指针的方法,我不确定它们是否应该是const。

我想我只是想了解const正确性的局限性和好处,以及如何预先确定某些东西是否为const以及如何正确应用const,因为将const放在不同的位置会改变含义。

编辑:同样,我如何处理'...丢弃限定词'。这究竟意味着什么?

6 个答案:

答案 0 :(得分:2)

使用const的位置取决于函数的用途。正如詹姆斯在评论中提出的那样(值得作为答案),将const放在任何地方:

如果该函数旨在修改其对象实例中的状态,const放在签名的末尾。

如果该函数旨在修改其中一个参考或指针参数,const放在参数上。

如果应修改指针或引用引用的变量const放在类型上(请记住,const紧接在之前适用于定义的部分。

如果返回的引用/指针引用了不应被接收的变量,执行const放在类型上。

在不知道函数的目的的情况下,回答问题中给出的示例是不可能的。我倾向于使用string ToString() constchar* ToString() const,以及关于谁负责delete char*的明确文档。


作为额外注释,const char*char const*是相同的(指向不可修改字符的指针)。另一方面,char* const是指向可修改字符的不可修改的指针。

答案 1 :(得分:1)

我总是将这些常见问题用作这些类型的问题作为起点。 http://www.parashift.com/c++-faq-lite/const-correctness.html

答案 2 :(得分:0)

您不能重载具有相同名称和相同参数但返回类型不同的函数。你可能知道这一点,但只是确定。

const括号后的

()表示该函数不会更改您调用它的对象。通常称为ToString的东西不会改变对象,所以在所有情况下你可能都需要一个const方法。

返回string和返回const string&之间的区别在于引用不会进行对象复制并且可能更快,但只有在您已经拥有{{1}时才能执行此操作} object(例如,作为string的私有成员)。如果不是(比如你需要将几个数据分块然后返回该字符串),你需要按值返回MyClass

使用string对象通常比使用C风格的string指针更受欢迎,但是因为你问:第四个char*,会让其他代码更改返回的字符字符串,这可能是一件坏事。 char*const char*char const*都是一样的。 const char const*在技术上是不同的,但由于返回char *const无关紧要的原因,返回类型不会很多:调用者可以只复制然后更改返回值。

简而言之,最好的形式是:

const int

答案 3 :(得分:0)

问题的一些变化是返回stringchar *。我认为这与const讨论无关(如果不是,请告诉我);我正在考虑string回复变化。

class MyClass
{
  string ToString();              // A
  string & ToString();            // B   (I added this)
  const string& ToString();       // C 
  const string& ToString() const; // D
};

我的偏好按此顺序排列:D,C,B,A。

在所有变体中,const以两种方式使用:

  • 返回类型说明符[D]中的第一个const

    这意味着返回的对象不能用于修改返回的对象。这句话听起来很有趣,不是吗?好吧,可能还有其他修改对象的方法,而const无法阻止它。请参阅此FAQ item

  • 类不变[D]中的第二个const

    这意味着该方法不会改变(修改)类对象。

我更喜欢D而不是其他任何因为D保证不会修改调用该方法的对象。如果可以在不修改对象的情况下实现目标(即可以实现方法),那么在设计方面就是一个巨大的胜利。我尽可能地使用它。 但是如果必须修改对象 (即,如果不修改对象就无法实现该方法),则排除D。

其余的B和C都优于A,因为B和C返回引用,这避免了A中所需的复制构造。

在B和C之间,C是优选的,因为它返回const引用。

答案 4 :(得分:-1)

我发现this是一个有用的指南

答案 5 :(得分:-1)

  

你用什么经验法则决定什么时候应该是const?

随时随地使用它。然后,当您需要修改对象或授予对可能修改对象的内容的访问权限(即将引用或代理返回到内部状态)时,使用它。

  

第三个可能是胡说八道,因为引用总是不变的是正确的吗?

不,这不正确。引用是别名,而不是变量。因此,您无法更改引用“指向”哪个变量,就像使用指针一样。但是,您可能引用了一个可变对象(std::string&)。

  

所有这些ToString方法之间有什么区别?

他们在内存管理技术方面差异很大,但从高层次来看,他们都做同样的事情,除了以下内容:

char* ToString();

该ont返回指向可变字符数组的指针(可能是内部状态)。

请注意以下系列:

char const* ToString();
const char* ToString(); // or this?
const char const* ToString(); // Is this legal?

是写同一件事的不同方法。无论你是否写入,本机类型都是按值返回的const。

以下2是C ++中返回字符串的首选方式(在最后提供了额外的const):

string ToString(); // this one?
const string& ToString(); // or this?

您将使用哪两个取决于您从哪里获得价值。如果字符串是数据成员,我建议你选择后者,因为它通常更快,但如果你的字符串实现使用Copy-On-Write语义则不是很多。如果你必须计算一个值并返回它,你必须使用前者,因为你不能返回对局部变量的引用。

以下两项都是正确的,但我仍然建议您使用std::string

const char* ToString() const; // or this?
const char const* ToString() const; // how about this?