const关键字
来源:互联网 发布:网络打印机无法连接 编辑:程序博客网 时间:2024/06/02 13:47
The const keyword.
The const keyword is used to create a read only variable. Once initialised, the value of the variable cannot be changed but can be used just like any other variable.
const syntax
main() { const float pi = 3.14; }
The const keyword is used as a qualifier to the following data types - int float char double struct.
const int degrees = 360; const float pi = 3.14; const char quit = 'q';
const and pointers.
Consider the following example.
void Func(const char *Str); main() { char *Word; Word = (char *) malloc(20); strcpy(Word, "Sulphate"); Func(Word); } void Func(const char *Str) { }
The const char *Str
tells the compiler that the DATA the pointer points too is const
. This means, Str can be changed within Func, but *Str cannot. As a copy of the pointer is passed to Func, any changes made to Str are not seen by main....
-------- | Str | Value can be changed -----|-- | | V -------- | *Str | Read Only - Cannot be changed. --------
Geeky Stuff
It is still possible to change the contents of a 'const' variable. Consider this program it creates a const variable and then changes its value by accessing the data by another name.I am not sure if this applies to all compilers, but, you can place the 'const' after the datatype, for example:
int const degrees = 360; float const pi = 3.14; char const quit = 'q';
are all valid in 'gcc'.
More Geeky Stuff
What would you expect these to do?
main() { const char * const Variable1; char const * const Variable2; };
These both make the pointer and the data read only. Here are a few more examples.
const int Var; /* Var is constant */ int const Var; /* Ditto */ int * const Var; /* The pointer is constant, * the data its self can change. */ const int * Var; /* Var can not be changed. */
[18] Const correctness
(Part of C++ FAQ Lite, Copyright © 1991-2006, Marshall Cline, cline@parashift.com)
FAQs in section [18]:
- [18.1] What is "const correctness"?
- [18.2] How is "const correctness" related to ordinary type safety?
- [18.3] Should I try to get things const correct "sooner" or "later"?
- [18.4] What does "
const Fred* p " mean? - [18.5] What's the difference between "
const Fred* p ", "Fred* const p " and "const Fred* const p "? - [18.6] What does "
const Fred& x " mean? - [18.7] Does "
Fred& const x " make any sense? - [18.8] What does "
Fred const& x " mean? - [18.9] What does "
Fred const* x " mean? - [18.10] What is a "const member function"?
- [18.11] What's the relationship between a return-by-reference and a const member function?
- [18.12] What's the deal with "const-overloading"?
- [18.13] What do I do if I want a const member function to make an "invisible" change to a data member?
- [18.14] Does const_cast mean lost optimization opportunities?
- [18.15] Why does the compiler allow me to change an int after I've pointed at it with a
const int* ? - [18.16] Does "
const Fred* p " mean that*p can't change? - [18.17] Why am I getting an error converting a
Foo** →const Foo** ?
[18.1] What is "const correctness"?
A good thing. It means using the keyword const to prevent const objects from getting mutated.
For example, if you wanted to create a function
void f1(const std::string& s); // Pass by reference-to-constvoid f2(const std::string* sptr); // Pass by pointer-to-constvoid f3(std::string s); // Pass by value
In the pass by reference-to-const and pass by pointer-to-const cases, any attempts to change to the caller's
As an opposite example, if you wanted to create a function
void g1(std::string& s); // Pass by reference-to-non-constvoid g2(std::string* sptr); // Pass by pointer-to-non-const
The lack of const in these functions tells the compiler that they are allowed to (but are not required to) change the caller's
void f1(const std::string& s)
{
g1(s); // Compile-time Error since s is const
std::string localCopy = s;
g1(localCopy); // OK since localCopy is not const
}
Naturally in the above case, any changes that
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.2] How is "const correctness" related to ordinary type safety?
Declaring the const-ness of a parameter is just another form of type safety. It is almost as if a const
If you find ordinary type safety helps you get systems correct (it does; especially in large systems), you'll find const correctness helps also.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.3] Should I try to get things const correct "sooner" or "later"?
At the very, very, very beginning.
Back-patching const correctness results in a snowball effect: every const you add "over here" requires four more to be added "over there."
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.4] What does "const Fred* p " mean?
It means p points to an object of class Fred, but p can't be used to change that Fred object (naturally p could also be NULL).
For example, if class Fred has a const member function called
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.5] What's the difference between "const Fred* p ", "Fred* const p " and "const Fred* const p "?
You have to read pointer declarations right-to-left.
const Fred* p means "p points to a Fred that is const" — that is, the Fred object can't be changed via p.Fred* const p means "p is a const pointer to a Fred" — that is, you can change the Fred object via p, but you can't change the pointer p itself.const Fred* const p means "p is a const pointer to a const Fred" — that is, you can't change the pointer p itself, nor can you change the Fred object via p.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.6] What does "const Fred& x " mean?
It means x aliases a Fred object, but x can't be used to change that Fred object.
For example, if class Fred has a const member function called
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.7] Does "Fred& const x " make any sense?
No, it is nonsense.
To find out what the above declaration means, you have to read it right-to-left. Thus "
In other words, "
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.8] What does "Fred const& x " mean?
Answer: absolutely no one should pretend they can make decisions for your organization until they know something about your organization. One size does not fit all; there is no "right" answer for all organizations, so do not allow anyone to make a knee-jerk decision in either direction. "Think" is not a four-letter word.
For example, some organizations value consistency and have tons of code using
Use a style that is appropriate for your organization's average maintenance programmer. Not the gurus, not the morons, but the average maintenance programmer. Unless you're willing to fire them and hire new ones, make sure that they understand your code. Make a business decision based on your realities, not based on someone else's assumptions.
You'll need to overcome a little inertia to go with
Another caveat: if you decide to use
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.9] What does "Fred const* x " mean?
Answer: absolutely no one should pretend they can make decisions for your organization until they know something about your organization. One size does not fit all; there is no "right" answer for all organizations, so do not allow anyone to make a knee-jerk decision in either direction. "Think" is not a four-letter word.
For example, some organizations value consistency and have tons of code using
Use a style that is appropriate for your organization's average maintenance programmer. Not the gurus, not the morons, but the average maintenance programmer. Unless you're willing to fire them and hire new ones, make sure that they understand your code. Make a business decision based on your realities, not based on someone else's assumptions.
You'll need to overcome a little inertia to go with
Another caveat: if you decide to use
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.10] What is a "const member function"?
A member function that inspects (rather than mutates) its object.
A const member function is indicated by a const suffix just after the member function's parameter list. Member functions with a const suffix are called "const member functions" or "inspectors." Member functions without a const suffix are called "non-const member functions" or "mutators."
public:
void inspect() const; // This member promises NOT to change
void mutate(); // This member function might change
};
void userCode(Fred& changeable, const Fred& unchangeable)
{
changeable.inspect(); // OK: doesn't change a changeable object
changeable.mutate(); // OK: changes a changeable object
unchangeable.inspect(); // OK: doesn't change an unchangeable object
unchangeable.mutate(); // ERROR: attempt to change unchangeable object
}
The error in
The trailing const on
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.11] What's the relationship between a return-by-reference and a const member function?
If you want to return a member of your this object by reference from an inspector method, you should return it using reference-to-const, that is,
public:
const std::string& name_good() const; ← Right: the caller can't change the name
std::string& name_evil() const; ← Wrong: the caller can change the name
...
};
void myCode(const Person& p) ← You're promising not to change the Person object...
{
p.name_evil() = "Igor"; ← ...but you changed it anyway!!
}
The good news is that the compiler will often catch you if you get this wrong. In particular, if you accidentally return a member of your this object by non-const reference, such as in
The bad news is that the compiler won't always catch you: there are some cases where the compiler simply won't ever give you a compile-time error message.
Net: you need to think, and you need to remember the guideline in this FAQ. If the thing you are returning by reference is logically part of your this object, independent of whether it is physically embedded within your this object, then a const method needs to return by const reference or by value, but not by non-const reference. (The idea of "logically" part of your this object is related to the notion of an object's "abstract state"; see the previous FAQ for more.)
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.12] What's the deal with "const-overloading"?
It's when you have an inspector method and a mutator method with the same name and the same number and type of parameters — the methods differ only in that one is const and the other is non-const.
The subscript operator is a common use of const-overloading. You should generally try to use one of the standard container templates, such as
class MyFredList {
public:
const Fred& operator[] (unsigned index) const; ← subscript operators often come in pairs
Fred& operator[] (unsigned index); ← subscript operators often come in pairs
...
};
When you apply the subscript operator to a MyFredList object that is non-const, the compiler will call the non-const subscript operator. Since that returns a normal
{
// Okay to call methods that DON'T change the Fred at
Fred x = a[3];
a[3].inspect();
// Okay to call methods that DO change the Fred at
Fred y;
a[3] = y;
a[3].mutate();
}
However when you apply the subscript operator to a
{
// Okay to call methods that DON'T change the Fred at
Fred x = a[3];
a[3].inspect();
// Error (fortunately!) if you try to change the Fred at
Fred y;
a[3] = y; ← Fortunately(!) the compiler catches this error at compile-time
a[3].mutate(); ← Fortunately(!) the compiler catches this error at compile-time
}
Const overloading for subscript- and funcall-operators is illustrated in FAQ [13.10], [16.17], [16.18], [16.19], and [35.2].
You can, of course, also use const-overloading for things other than the subscript operator.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.13] What do I do if I want a const member function to make an "invisible" change to a data member?
Use mutable (or, as a last resort, use const_cast).
A small percentage of inspectors need to make innocuous changes to data members (e.g., a Set object might want to cache its last lookup in hopes of improving the performance of its next lookup). By saying the changes are "innocuous," I mean that the changes wouldn't be visible from outside the object's interface (otherwise the member function would be a mutator rather than an inspector).
When this happens, the data member which will be modified should be marked as mutable (put the mutable keyword just before the data member's declaration; i.e., in the same place where you could put const). This tells the compiler that the data member is allowed to change during a const member function. If your compiler doesn't support the mutable keyword, you can cast away the const'ness of this via the const_cast keyword (but see the NOTE below before doing this). E.g., in
// See the NOTE below before doing this!
After this line, self will have the same bits as this (e.g.,
NOTE: there is an extremely unlikely error that can occur with const_cast. It only happens when three very rare things are combined at the same time: a data member that ought to be mutable (such as is discussed above), a compiler that doesn't support the mutable keyword, and an object that was originally defined to be const (as opposed to a normal, non-const object that is pointed to by a pointer-to-const). Although this combination is so rare that it may never happen to you, if it ever did happen the code may not work (the Standard says the behavior is undefined).
If you ever want to use const_cast, use mutable instead. In other words, if you ever need to change a member of an object, and that object is pointed to by a pointer-to-const, the safest and simplest thing to do is add mutable to the member's declaration. You can use const_cast if you are sure that the actual object isn't const (e.g., if you are sure the object is declared something like this: Set
Please don't write and tell me that version X of compiler Y on machine Z allows you to change a non-mutable member of a const object. I don't care — it is illegal according to the language and your code will probably fail on a different compiler or even a different version (an upgrade) of the same compiler. Just say no. Use mutable instead.
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.14] Does const_cast mean lost optimization opportunities?
In theory, yes; in practice, no.
Even if the language outlawed const_cast, the only way to avoid flushing the register cache across a const member function call would be to solve the aliasing problem (i.e., to prove that there are no non-const pointers that point to the object). This can happen only in rare cases (when the object is constructed in the scope of the const member function invocation, and when all the non-const member function invocations between the object's construction and the const member function invocation are statically bound, and when every one of these invocations is also inlined, and when the constructor itself is inlined, and when any member functions the constructor calls are inline).
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.15] Why does the compiler allow me to change an int after I've pointed at it with a const int* ?
Because "
Causing a
{
int i = *p1; // Get the (original) value of
*p2 = 7; // If
int j = *p1; // Get the (possibly new) value of
if (i != j) {
std::cout << "*p1 changed, but it didn't change via pointer p1!/n";
assert(p1 == p2); // This is the only way
}
}
int main()
{
int x = 5;
f(&x, &x); // This is perfectly legal (and even moral!)
...
}
Note that
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.16] Does "const Fred* p " mean that *p can't change?
No! (This is related to the FAQ about aliasing of int pointers.)
"
public:
void inspect() const; // A const member function
void mutate(); // A non-const member function
};
int main()
{
Fred f;
const Fred* p = &f;
Fred* q = &f;
p->inspect(); // OK: No change to
p->mutate(); // Error: Can't change
q->inspect(); // OK: q is allowed to inspect the object
q->mutate(); // OK: q is allowed to mutate the object
f.inspect(); // OK: f is allowed to inspect the object
f.mutate(); // OK: f is allowed to mutate the object
...
}
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
[18.17] Why am I getting an error converting a Foo** → const Foo** ?
Because converting
C++ allows the (safe) conversion
The rationale for why that error is a good thing is given below. But first, here is the most common solution: simply change
void f(const Foo** p);
void g(const Foo* const* p);
int main()
{
Foo** p = /*...*/;
...
f(p); // ERROR: it's illegal and immoral to convert
g(p); // OK: it's legal and moral to convert
...
}
The reason the conversion from
public:
void modify(); // make some modify to the this object
};
int main()
{
const Foo x;
Foo* p;
const Foo** q = &p; // q now points to p; this is (fortunately!) an error
*q = &x; // p now points to x
p->modify(); // Ouch: modifies a
...
}
Reminder: please do not pointer-cast your way around this. Just Say No!
[ Top | Bottom | Previous section | Next section | Search the FAQ ]
E-mail the author
[ C++ FAQ Lite | Table of contents | Subject index | About the author | © | Download your own copy ]
Revised Sep 25, 2006
- const关键字
- const关键字
- const关键字
- 关键字const
- const关键字
- const关键字
- const关键字
- const 关键字
- 关键字 const
- const关键字
- const关键字
- const关键字
- const关键字
- const关键字
- const关键字
- const关键字
- 关键字 const
- const关键字
- 随便写点东西吧,嘻嘻!!
- 也谈西游团队裁员的问题
- Asp.net动态生成html页面
- 转C++中的虚函数(virtual function)
- javascript单选按钮的处理方式
- const关键字
- C#实现web信息自动抓取
- 刚开的博客
- gdb使用
- java显示系统的时间.jsp的复选框操作
- 接口例子[转]
- 看到一段代码,思考Element
- 数据库 查询优化
- 如何将FAT32格式转换为NTFS格式(一)