C++ “const”最后在类的函数声明中的含义?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/751681/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:05:39  来源:igfitidea点击:

Meaning of 'const' last in a function declaration of a class?

c++constdeclarationc++-faq

提问by Mats Fredriksson

What is the meaning of constin declarations like these? The constconfuses me.

const像这样的声明是什么意思?这const让我很困惑。

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

回答by Mats Fredriksson

When you add the constkeyword to a method the thispointer will essentially become a pointer to constobject, and you cannot therefore change any member data. (Unless you use mutable, more on that later).

当您将const关键字添加到方法时,this指针本质上将成为指向const对象的指针,因此您不能更改任何成员数据。(除非您使用mutable,稍后会详细介绍)。

The constkeyword is part of the functions signature which means that you can implement two similar methods, one which is called when the object is const, and one that isn't.

const关键字是函数的签名,这意味着你可以实现两个类似的方法,当一个对象是被称为的一部分const,和一个不是。

#include <iostream>

class MyClass
{
private:
    int counter;
public:
    void Foo()
    { 
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        std::cout << "Foo const" << std::endl;
    }

};

int main()
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
}

This will output

这将输出

Foo
Foo const

In the non-const method you can change the instance members, which you cannot do in the constversion. If you change the method declaration in the above example to the code below you will get some errors.

在非常量方法中,您可以更改实例成员,而在const版本中不能这样做。如果将上面示例中的方法声明更改为下面的代码,则会出现一些错误。

    void Foo()
    {
        counter++; //this works
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++; //this will not compile
        std::cout << "Foo const" << std::endl;
    }

This is not completely true, because you can mark a member as mutableand a constmethod can then change it. It's mostly used for internal counters and stuff. The solution for that would be the below code.

这并不完全正确,因为您可以将成员标记为mutableconst然后方法可以更改它。它主要用于内部计数器和东西。解决方案是下面的代码。

#include <iostream>

class MyClass
{
private:
    mutable int counter;
public:

    MyClass() : counter(0) {}

    void Foo()
    {
        counter++;
        std::cout << "Foo" << std::endl;    
    }

    void Foo() const
    {
        counter++;    // This works because counter is `mutable`
        std::cout << "Foo const" << std::endl;
    }

    int GetInvocations() const
    {
        return counter;
    }
};

int main(void)
{
    MyClass cc;
    const MyClass& ccc = cc;
    cc.Foo();
    ccc.Foo();
    std::cout << "Foo has been invoked " << ccc.GetInvocations() << " times" << std::endl;
}

which would output

哪个会输出

Foo
Foo const
Foo has been invoked 2 times

回答by Blair Conrad

The const means that the method promises not to alter any members of the class. You'd be able to execute the object's members that are so marked, even if the object itself were marked const:

const 意味着该方法承诺不会更改类的任何成员。即使对象本身被标记,您也可以执行被标记的对象成员const

const foobar fb;
fb.foo();

would be legal.

将是合法的。

See How many and which are the uses of “const” in C++?for more information.

请参阅C++ 中“const”的用途有多少?想要查询更多的信息。

回答by JaredPar

The constqualifier means that the methods can be called on any value of foobar. The difference comes when you consider calling a non-const method on a const object. Consider if your foobartype had the following extra method declaration:

const预选赛的手段,该方法可以在任何值调用foobar。当您考虑在 const 对象上调用非常量方法时,就会出现差异。考虑您的foobar类型是否具有以下额外的方法声明:

class foobar {
  ...
  const char* bar();
}

The method bar()is non-const and can only be accessed from non-const values.

该方法bar()是非常量的,只能从非常量值访问。

void func1(const foobar& fb1, foobar& fb2) {
  const char* v1 = fb1.bar();  // won't compile
  const char* v2 = fb2.bar();  // works
}

The idea behind constthough is to mark methods which will not alter the internal state of the class. This is a powerful concept but is not actually enforceable in C++. It's more of a promise than a guarantee. And one that is often broken and easily broken.

背后的想法const是标记不会改变类内部状态的方法。这是一个强大的概念,但实际上并不能在 C++ 中强制执行。与其说是保证,不如说是一种承诺。和一个经常坏和容易坏的。

foobar& fbNonConst = const_cast<foobar&>(fb1);

回答by Mykola Golubyev

These const mean that compiler will Error if the method 'with const' changes internal data.

这些 const 意味着如果“with const”方法更改内部数据,编译器将出错。

class A
{
public:
    A():member_()
    {
    }

    int hashGetter() const
    {
        state_ = 1;
        return member_;
    }
    int goodGetter() const
    {
        return member_;
    }
    int getter() const
    {
        //member_ = 2; // error
        return member_;
    }
    int badGetter()
    {
        return member_;
    }
private:
    mutable int state_;
    int member_;
};

The test

考试

int main()
{
    const A a1;
    a1.badGetter(); // doesn't work
    a1.goodGetter(); // works
    a1.hashGetter(); // works

    A a2;
    a2.badGetter(); // works
    a2.goodGetter(); // works
    a2.hashGetter(); // works
}

Read thisfor more information

阅读本文了解更多信息

回答by Alnitak

Blair's answer is on the mark.

布莱尔的回答恰到好处。

However note that there is a mutablequalifier which may be added to a class's data members. Any member so marked canbe modified in a constmethod without violating the constcontract.

但是请注意,有一个mutable限定符可以添加到类的数据成员中。任何如此标记的成员可以在const不违反const合同的情况下以一种方法进行修改。

You might want to use this (for example) if you want an object to remember how many times a particular method is called, whilst not affecting the "logical" constness of that method.

如果您希望对象记住调用特定方法的次数,同时不影响该方法的“逻辑”常量,则您可能想要使用它(例如)。

回答by Nan Xiao

Meaning of a Const Member Functionin C++ Common Knowledge: Essential Intermediate Programminggives a clear explanation:

一个const成员函数的意义C ++常识:基本中级设计给出了明确的解释:

The type of the this pointer in a non-const member function of a class X is X * const. That is, it's a constant pointer to a non-constant X (see Const Pointers and Pointers to Const [7, 21]). Because the object to which this refers is not const, it can be modified. The type of this in a const member function of a class X is const X * const. That is, it's a constant pointer to a constant X. Because the object to which this refers is const, it cannot be modified. That's the difference between const and non-const member functions.

类 X 的非常量成员函数中 this 指针的类型为 X * const。也就是说,它是一个指向非常量 X 的常量指针(参见 Const Pointers 和 Pointers to Const [7, 21])。因为 this 指向的对象不是 const,所以可以修改。类 X 的 const 成员函数中的 this 类型为 const X * const。也就是说,它是一个指向常量 X 的常量指针。因为 this 指向的对象是常量,所以它不能被修改。这就是 const 和非常量成员函数之间的区别。

So in your code:

所以在你的代码中:

class foobar
{
  public:
     operator int () const;
     const char* foo() const;
};

You can think it as this:

你可以这样想:

class foobar
{
  public:
     operator int (const foobar * const this) const;
     const char* foo(const foobar * const this) const;
};

回答by Matrix Buster

when you use constin the method signature (like your said: const char* foo() const;) you are telling the compiler that memory pointed to by thiscan't be changed by this method (which is foohere).

当您const在方法签名中使用时(如您所说const char* foo() const;的:),您是在告诉编译器指向的内存this不能被此方法(foo此处)更改。

回答by coder3101

I would like to add the following point.

我想补充以下几点。

You can also makeit a const &and const &&

你也可以把它变成一个const &const &&

So,

所以,

struct s{
    void val1() const {
     // *this is const here. Hence this function cannot modify any member of *this
    }
    void val2() const & {
    // *this is const& here
    }
    void val3() const && {
    // The object calling this function should be const rvalue only.
    }
    void val4() && {
    // The object calling this function should be rvalue reference only.
    }

};

int main(){
  s a;
  a.val1(); //okay
  a.val2(); //okay
  // a.val3() not okay, a is not rvalue will be okay if called like
  std::move(a).val3(); // okay, move makes it a rvalue
}

Feel free to improve the answer. I am no expert

随意改进答案。我不是专家

回答by Chandra Shekhar

The constkeyword used with the function declaration specifies that it is a const member functionand it will not be able to changethe data members of the object.

与函数声明一起使用的const关键字指定它是一个const 成员函数,并且不能更改对象的数据成员。

回答by qwr

https://isocpp.org/wiki/faq/const-correctness#const-member-fns

https://isocpp.org/wiki/faq/const-correctness#const-member-fns

What is a "constmember function"?

A member function that inspects (rather than mutates) its object.

A constmember function is indicated by a constsuffix just after the member function's parameter list. Member functions with a constsuffix are called “const member functions” or “inspectors.” Member functions without a constsuffix are called “non-const member functions” or “mutators.”

class Fred {
public:
  void inspect() const;   // This member promises NOT to change *this
  void mutate();          // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
  changeable.inspect();   // Okay: doesn't change a changeable object
  changeable.mutate();    // Okay: changes a changeable object
  unchangeable.inspect(); // Okay: doesn't change an unchangeable object
  unchangeable.mutate();  // ERROR: attempt to change unchangeable object
}

The attempt to call unchangeable.mutate()is an error caught at compile time. There is no runtime space or speed penalty for const, and you don't need to write test-cases to check it at runtime.

The trailing conston inspect()member function should be used to mean the method won't change the object's abstract(client-visible) state. That is slightly different from saying the method won't change the “raw bits” of the object's struct. C++ compilers aren't allowed to take the “bitwise” interpretation unless they can solve the aliasing problem, which normally can't be solved (i.e., a non-const alias could exist which could modify the state of the object). Another (important) insight from this aliasing issue: pointing at an object with a pointer-to-const doesn't guarantee that the object won't change; it merely promises that the object won't change via that pointer.

什么是“const成员函数”?

检查(而不是改变)其对象的成员函数。

一个const成员函数由表示const后缀只是成员函数的参数列表之后。带有const后缀的成员函数称为“const 成员函数”或“检查员”。没有const后缀的成员函数称为“非常量成员函数”或“mutators”。

class Fred {
public:
  void inspect() const;   // This member promises NOT to change *this
  void mutate();          // This member function might change *this
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
  changeable.inspect();   // Okay: doesn't change a changeable object
  changeable.mutate();    // Okay: changes a changeable object
  unchangeable.inspect(); // Okay: doesn't change an unchangeable object
  unchangeable.mutate();  // ERROR: attempt to change unchangeable object
}

尝试调用unchangeable.mutate()是在编译时捕获的错误。没有运行时空间或速度损失const,并且您不需要编写测试用例来在运行时检查它。

尾部constinspect()成员函数应用于表示该方法不会改变该对象的抽象(客户端可见的)的状态。这与说该方法不会更改对象结构的“原始位”略有不同。C++ 编译器不允许采用“按位”解释,除非它们可以解决通常无法解决的别名问题(即,可能存在可以修改对象状态的非常量别名)。这个别名问题的另一个(重要)见解是:使用指向常量的指针指向一个对象并不能保证该对象不会改变;它只是承诺对象不会通过该指针改变。