【问题标题】:Different placement of const keyword in method declarations?方法声明中 const 关键字的不同位置?
【发布时间】:2013-10-07 06:27:29
【问题描述】:

stackoverflow 上有类似问题的一些答案,但所有答案都不完整或没有比较(有不同的例子)。我看到了至少 3 种可能的声明情况:

  1. const void f();
  2. void f() const;
  3. const void f() const;

它们有什么区别?

我发现的唯一区别是以下代码仅适用于 (2) 或 (3):

const foobar fb;
fb.foo();

【问题讨论】:

  • void const f() volatile && 怎么样?还是volatile void f() & final
  • 提示:永远不要声明返回类型const(如1和3)。如果没有返回类型(如这里),那是没有意义的;基本无害,但对简单类型不是特别有用;但对更复杂的类型可能有害,因为它会阻止移动语义。
  • 对不起,我写的“void”仅作为示例

标签: c++ methods comparison constants


【解决方案1】:
  1. const 在这个位置声明返回类型为const
  2. 此位置的const 仅可用于成员函数,这意味着该函数不能/不会修改任何非mutable 成员变量(对象常量)。
  3. 这是以上 2 的组合。

【讨论】:

  • 错了。在 1 中,const 被简单地忽略。而 2 只是一个约定。
  • 我想你会发现问题中的空白只是类型的填充物。
  • 查看问题下的评论。
  • 有时候有用,看我的回答
【解决方案2】:

方法名称之前的const(如您的问题的第 1 点和第 3 点)指的是返回类型。这意味着函数的结果是不可修改的;但是这个 const 何时真正有意义是有限制的——基本上,它通常只对用户定义的类型有意义。不过,在 void 返回类型的上下文中它意味着什么,我目前不知道。我最好的猜测是它只是被编译器忽略了。

方法名称后面的const(如第 2 点和第 3 点)使整个方法为 const,这意味着该方法不能修改任何成员(声明的 mutable 除外)。

由于您的 foobar 变量被声明为 const 并且因此不能被修改,因此只能调用其上的 const 方法,这就是为什么只有 2. 和 3. 有效(它们都声明了 方法 const; 在 1. 它只是返回类型是 const!)

【讨论】:

  • 函数的返回值是一个右值。非 const 类型的右值不是 cv 限定的,因此 void const 与简单的 void 相同。
  • 你所说的 2 只是一个约定(并不是真正的约定:通常的约定是 const 函数不会修改可观察状态,也不会返回任何允许修改它的东西没有“破坏”常量)。
  • “你所说的 2 只是一个约定”——我所说的是编译器(或多或少)强制执行的;在我看来,您所说的似乎只是一个约定(编译器无法完全执行它,但这当然是要争取的东西)-否则我不明白您所说的“只是一个约定”是什么意思?
  • 编译器对const 函数所做的唯一事情就是更改this 的类型。函数仍然可以const_cast 将其返回为非常量,或者通过其他方式获得指向对象的非常量指针。 “约定”是它不会修改“可观察状态”(无论在上下文中意味着什么)。
【解决方案3】:

通常,const 会修改紧接在其前面的内容(并且 应始终在其修改后立即写入)。 在您显示的情况下:

const void f();

常量被忽略。不要写这样的东西;它令人困惑 读者。

void f() const;

这声明了一个“const”函数(因为const 是 紧跟在函数声明之前。的概念 const 函数有点特殊:它只适用于 非静态成员函数,这意味着 this 将是 T const*,而不是 T*。在实践中,它是 被视为不修改可观察状态的承诺 调用函数的对象。

const void f() const;

与先例完全一样。第一个const 是 忽略。

当然还有很多其他的地方const可以出现:

void const* f();

例如,声明一个返回指针的函数 一个常量无效。 (你会经常看到这个写成

const void* f();

如果const 之前没有任何内容,那么它适用于 跟随。但是,作为一般规则,最好避免 这种风格,即使它很普遍。)

请注意与您最初所写内容的区别 例子。这里,返回类型是一个指针,const 适用于所指向的内容,而不适用于指针(这将 是void *const)。虽然顶级 const 被忽略 非类返回类型(所以 void *const f();void* f();),这适用于其他 const。

【讨论】:

    【解决方案4】:
    1)    const void f();
    

    返回类型称为常量。在模板中的示例中很有用,其中忽略 void 上的 cv-qualifications 或在编译器实现和最终用户代码方面使它们成为错误 could create unnecessary complexity。例如:

      template<typename T>
      const T ...
    

    函数的返回值是一个右值。 non-const 类型的右值不是cv-qualified,所以void const 与简单的void 相同——在这种情况下const 被忽略。虽然const void 不是很有帮助,但const void* 有它的用途。 g++ 确认const void 可能很重要,因为以下代码无法编译

    #include <type_traits>
    
    static_assert(std::is_same<void(), const void()>::value, "const matters");
    
    2)    void f() const;
    

    指类成员。这个函数声明不更改类/结构的任何(非可变)成员,也不返回任何允许在不“破坏”常量的情况下修改它的东西。这就是为什么只能在常量对象上调用此类函数的原因

    const foobar fb;
    fb.foo();  // OK
    

    但是

    void f();
    const foobar fb;
    fb.foo(); // error
    

    终于

    3)    const void f() const;
    

    以上两个一起

    【讨论】:

      【解决方案5】:

      在某些情况下会使用const 关键字(包括您询问的情况以及其他一些情况)

      1.声明的常量

      const int constant_variable = 2;

      常量变量(上例中为constant_variable)的值在赋值后无法更改。

      2.常量成员函数

      类 Foo { int a_member_func()const; int a_member_variable; 可变 int 可变变量; };

      一个常量成员函数被禁止改变其对象的成员变量。在这种情况下a_member_func()不允许更改a_member_varialbe,但特殊情况是常量成员函数可以更改标记为mutable的成员变量的值(a_member_func()可以更改mutable_variable

      3.Const引用参数和Const指针参数

      int a_func(const int& a, const int* b);

      在这种情况下,a_func() 不允许更改 ab 的值。常量引用参数和常量指针参数不能被它们传递给的函数改变。

      4.常量返回类型函数

      const int a_func();

      一个常量函数(在函数返回类型前面使用const关键字),总是返回一个常量值。这意味着a_func() 返回一个常量值。

      这不是 const 关键字用法的完整列表。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-06
        • 2013-02-25
        • 1970-01-01
        • 2011-09-29
        • 2018-11-07
        • 2013-02-15
        • 1970-01-01
        相关资源
        最近更新 更多