const
的意思是什么?class foobar
{
public:
operator int () const;
const char* foo() const;
};
const
的意思是什么?class foobar
{
public:
operator int () const;
const char* foo() const;
};
当你在一个方法中添加const
关键字时,this
指针本质上将成为指向const
对象的指针,因此你不能更改任何成员数据。(除非你使用mutable
,稍后会讲到)。
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();
}
这将会输出
Foo
Foo const
在非const方法中,您可以更改实例成员,而在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;
}
这并不完全正确,因为您可以将成员标记为mutable
,然后const
方法可以更改它。它主要用于内部计数器等内容。解决方案是以下代码。
#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;
}
输出结果如下:
Foo
Foo const
Foo has been invoked 2 times
const 表示该方法承诺不会更改类的任何成员。即使将对象本身标记为 const
,您仍然可以执行标记为这样的对象成员:
const foobar fb;
fb.foo();
是合法的。
更多信息请参见C++中“const”的用途有哪些以及数量是多少?。
const
限定符表示可以在任何foobar
值上调用方法。当您考虑在常量对象上调用非常量方法时,差异就出现了。假设您的foobar
类型具有以下额外方法声明:
class foobar {
...
const char* bar();
}
bar()
方法是非const的,只能从非const值中访问。
void func1(const foobar& fb1, foobar& fb2) {
const char* v1 = fb1.bar(); // won't compile
const char* v2 = fb2.bar(); // works
}
< p > "const" 的理念是标记那些不会改变类的内部状态的方法。这是一个强大的概念,但在 C++ 中实际上是无法执行的。它更像是一个承诺而不是保证。这个承诺经常被打破,也很容易被打破。
foobar& fbNonConst = const_cast<foobar&>(fb1);
const
的背后的想法是标记不会改变类内部状态的方法。”这正是我在寻找的。 - kovacconst
? - kovac这些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_;
};
测试
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
}
点击这里了解更多信息。
Blair的回答很到位。
但请注意,可以在类的数据成员中添加mutable
限定符。任何标记为 mutable 的成员都可以在const
方法中进行修改而不违反const
协定。
如果您想让对象记住调用特定方法的次数,同时不影响该方法的“逻辑”不可变性,则可能希望使用此选项(例如)。
class foobar
{
public:
operator int () const;
const char* foo() const;
};
class foobar
{
public:
operator int (const foobar * const this) const;
const char* foo(const foobar * const this) const;
};
this
不是 const
。它不能被修改的原因是它是一个 prvalue。 - Brian Bi我想添加以下观点。
你还可以将其声明为 const &
或 const &&
因此,
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
}
欢迎对答案进行改进。我不是专家。
当你在方法签名中使用const
(就像你所说的:const char* foo() const;
),你告诉编译器,被this
指向的内存不能被此方法(这里是foo
)更改。
这里的 const 表示在该函数中,任何变量的值都不能被改变。
class Test{
private:
int a;
public:
void test()const{
a = 10;
}
};
就像这个例子一样,如果你尝试在测试函数中更改变量的值,你将会收到一个错误。
https://isocpp.org/wiki/faq/const-correctness#const-member-fns
What is a "
const
member function"?A member function that inspects (rather than mutates) its object.
A
const
member function is indicated by aconst
suffix just after the member function’s parameter list. Member functions with aconst
suffix are called “const member functions” or “inspectors.” Member functions without aconst
suffix 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 forconst
, and you don’t need to write test-cases to check it at runtime.The trailing
const
oninspect()
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.
mutable
和const
对我来说是有意义的。但我不太理解的是,如果一个const
成员函数想要改变一个成员变量的值,为什么不丢弃const
并将自己变为非 const 的成员函数呢?这与速度有关吗?还是说在一个const
成员函数中,给定两个成员变量,一个带有mutable
关键字,另一个没有,我们只想更改具有mutable
关键字的变量的值,但希望保持另一个变量不变? - Lion Lai