`
huozheleisi
  • 浏览: 1234404 次
文章分类
社区版块
存档分类
最新评论

The const keyword

 
阅读更多
const int myconstant = 10
An int which can't change value. Similar to #define in C but better.
const int * myconstant
Variable pointer to a constant integer.
int const * myconstant
Same as above.
int * const myconstant
Constant pointer to a variable integer.
int const * const myconstant
Constant pointer to a constant integer.
void mymethod(QString const & myparamater)
myparamater will not be altered by the method. & means it can be altered but here we just want it to be used because it saves taking a copy.
class myclass {
void mymethod() const;
int myvariable; }
mymethod() will not alter any member variable (myvariable), this means you can call the method from a const variable.
const int*const mymethod(const int*const&)const
It will return a pointer which is constant and points to a constant integer, the method doesn't alter either the variable pointed to by the paramater or the pointer itself and it doesn't alter any of the member variables of the object the method is it.

The 'const' system is one of the really messy features of C++.

It is simple in concept, variables declared with ‘const’ added become constants and cannot be altered by the program, but, in the way is has to be used to bodge in a substitute for one of the missing features of C++, it gets horridly complicated and frustratingly restrictive. The following attempts to explain how 'const' is used and why it exists.

Simple Use of ‘const’

The simplest use is to declare a named constant. To do this, one declares a constant as if it was a variable but add ‘const’ before it. One has to initialise it immediately in the constructor because, of course, one cannot set the value later as that would be altering it. For example,

const int Constant1=96;

will create an integer constant, unimaginatively called ‘Constant1’, with the value 96.

Such constants are useful for parameters which are used in the program but are do not need to be changed after the program is compiled. It has an advantage for programmers over the C preprocessor ‘#define’ command in that it is understood & used by the compiler itself, not just substituted into the program text by the preprocessor before reaching the main compiler, so error messages are much more helpful.

It also works with pointers but one has to be careful where ‘const’ to determine whether the pointer or what it points to is constant or both. For example,

const int * Constant2

declares that Constant2 is variable pointer to a constant integer and

int const * Constant2

is an alternative syntax which does the same, whereas

int * const Constant3

declares that Constant3 is constant pointer to a variable integer and

int const * const Constant4

declares that Constant4 is constant pointer to a constant integer. Basically ‘const’ applies to whatever is on its immediate left (other than if there is nothing there in which case it applies to whatever is its immediate right).

Use of ‘const’ in Functions Return Values

Of the mixes of pointers and ‘const’, the constant pointer to a variable is useful for storage that can be changed in value but not moved in memory and the pointer (constant or otherwise) is useful for returning constant strings and arrays from functions which, because they are implemented as pointers, the program could otherwise try to alter and crash. Instead of a difficult to track down crash, the attempt to alter unalterable values will be detected during compilation.

For example, if a function which returns a fixed ‘Some text’ string is written like

char *Function1()
{ return “Some text”;}

then the program could crash if it accidentally tried to alter the value doing

Function1()[1]=’a’;

whereas the compiler would have spotted the error if the original function had been written

const char *Function1()
{ return "Some text";}

because the compiler would then know that the value was unalterable. (Of course, the compiler could theoretically have worked that out anyway but C is not that clever.)

Where it Gets Messy - in Parameter Passing

When a subroutine or function is called with parameters, variables passed as the parameters might be read from to transfer data into the subroutine/function, written to to transfer data back to the calling program or both to do both. Some languages enable one to specify this directly, such as having ‘in:’, ‘out:’ & ‘inout:’ parameter types, whereas in C one has to work at a lower level and specify the method for passing the variables choosing one that also allows the desired data transfer direction.

For example, a subroutine like

void Subroutine1(int Parameter1)
{ printf("%d",Parameter1);}

accepts the parameter passed to it in the default C & C++ way which is a copy. Therefore the subroutine can read the value of the variable passed to it but not alter it because any alterations it makes are only made to the copy and lost when the subroutine ends so

void Subroutine2(int Parameter1)
{ Parameter1=96;}

would leave the variable it was called with unchanged not set to 96.

The addition of an ‘&’ to the parameter name in C++ (which was a very confusing choice of symbol because an ‘&’ infront of variables elsewhere in C generate pointers!) like causes the actual variable itself, rather than a copy, to be used as the parameter in the subroutine and therefore can be written to thereby passing data back out the subroutine. Therefore

void Subroutine3(int &Parameter1)
{ Parameter1=96;}

would set the variable it was called with to 96. This method of passing a variable as itself rather than a copy is called a ‘reference’ in C.

That way of passing variables was a C++ addition to C. To pass an alterable variable in original C, a rather involved method using a pointer to the variable as the parameter then altering what it pointed to was used. For example

void Subroutine4(int *Parameter1)
{ *Parameter1=96;}

works but requires the every use of the variable in the called routine so altered and the calling routine altered to pass a pointer to the variable which is rather cumbersome.

But where does ‘const’ come into this? Well, there is a second common use for passing data by reference or pointer instead of copy. That is when copying a the variable would waste too much memory or take too long. This is particularly likely with large compound user-defined variable types (‘structures’ in C & ‘classes’ in C++). So a subroutine declared

void Subroutine4(big_structure_type &Parameter1);

might being using ‘&’ because it is going to alter the variable passed to it or it might just be to save copying time and there is no way to tell which it is if the function is compiled in someone else’s library. This could be a risk if one needs to trust the the subroutine not to alter the variable.

To solve this, ‘const’ can be used the in the parameter list like

void Subroutine4(big_structure_type const &Parameter1);

which will cause the variable to passed without copying but stop it from then being altered. This is messy because it is essentially making an in-only variable passing method from a both-ways variable passing method which was itself made from an in-only variable passing method just to trick the compiler into doing some optimization.

Ideally, the programmer should not need control this detail of specifying exactly how it variables are passed, just say which direction the information goes and leave the compiler to optimize it automatically, but C was designed for raw low-level programming on far less powerful computers than are standard these days so the programmer has to do it explicitly.

Messier Still - in the Object Oriented Programming

In Object Oriented Programming, calling a ‘method’ (the Object Oriented name for a function) of an object has gives an extra complication. As well as the variables in the parameter list, the method has access to the member variables of the object itself which are always passed directly not as copies. For example a trivial class, ‘Class1’, defined as

class Class1
{ void Method1();
int MemberVariable1;}

has no explicit parameters at all to ‘Method1’ but calling it in an object in this class might alter ‘MemberVariable1’ of that object if ‘Method1’ happened to be, for example,

void Class1::Method1()
{ MemberVariable1=MemberVariable1+1;}

The solution to that is to put ‘const’ after the parameter list like

class Class2
{ void Method1() const;
int MemberVariable1;}

which will ban Method1 in Class2 from being anything which can attempt to alter any member variables in the object.

Of course one sometimes needs to combine some of these different uses of ‘const’ which can get confusing as in

const int*const Method3(const int*const&)const;

where the 5 uses ‘const’ respectively mean that the variable pointed to by the returned pointer & the returned pointer itself won’t be alterable and that the method does not alter the variable pointed to by the given pointer, the given pointer itself & the object of which it is a method!.

Inconveniences of ‘const’

Besides the confusingness of the ‘const’ syntax, there are some useful things which the system prevents programs doing.

One in particular annoys me because my programs often need to be optimized for speed. This is that a method which is declared ‘const’ cannot even make changes to the hidden parts of its object that would not make any changes that would be apparent from the outside. This includes storing intermediary results of long calculations which would save processing time in subsequent calls to the class’s methods. Instead it either has to pass such intermediary results back to the calling routine to store and pass back next time (messy) or recalculate from scratch next time (inefficient). In later versions of C++, the ‘mutable’ keyword was added which enables ‘const’ to be overridden for this purpose but it totally relies on trusting the programmer to only use it for that purpose so, if you have to write a program using someone else's class which uses ‘mutable’ then you cannot guarantee that ‘‘mutable’ things will really be constant which renders ‘const’ virtually useless.

One cannot simply avoid using ‘const’ on class methods because ‘const’ is infectious. An object which has been made ‘const’, for example by being passed as a parameter in the ‘const &’ way, can only have those of its methods that are explicitly declared ‘const’ called (because C++’s calling system is too simple work out which methods not explicitly declared ‘const’ don’t actually change anything). Therefore class methods that don’t change the object are best declared ‘const’ so that they are not prevented from being called when an object of the class has somehow acquired ‘const’ status.

分享到:
评论

相关推荐

    Microsoft Visual C# 2013 Step by Step,最新资料

    Creating a static field by using the const keyword 177 Understanding static classes 177 Anonymous classes ...180 Summary .........181 Quick reference 182 Chapter 8 Understanding values and references ...

    JavaScript-Notes

    The 2015 version of JavaScript (ES6) allows the use of the const keyword to define a variable that cannot be reassigned, and the let keyword to define a variable with restricted scope. You can also ...

    keyword-extractor:NPM软件包,用于从字符串创建关键字数组并排除停用词

    关键字提取器 一个简单的用于通过删除停用词从字符串中提取关键字。 安装 $ npm install keyword-extractor 安装演示所需的browserify(修改...const keyword_extractor = require ( "keyword-extractor" ) ; // Ope

    QuickBasic自带的投掷游戏代码GORILLA.BAS

    QuickBasic自带的投掷游戏代码,很老很老了~ ' Q B a s i c G o r i l l a s ...' To get help on a BASIC keyword, move the cursor to the keyword and press ' F1 or click the right mouse button.

    Google C++ Style Guide(Google C++编程规范)高清PDF

    (One exception is if an argument Foo or const Foo& has a non-explicit, one-argument constructor, in which case we need the full definition to support automatic type conversion.) We can declare ...

    Using LUA with Visual C++ (Introduction)

    Tell the compiler that the function definitions are C style by enclosing the include directive with the extern keyword : extern "C" { #include } You can also define LUA_API before including lua.h :...

    王小平版遗传算法的光盘源代码

    Read the notes in the Makefiles in all the sub-directories, make any necessary changes to fit your system, and then type: make depend PROBLEM=PROBNAME make PROBLEM=PROBNAME where PROBNAME is the ...

    《深度探索C++对象模型》(Stanley B·Lippman[美] 著,侯捷 译)

    1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态...

    mdrscr:用于Mandarake搜索查询的简单刮板库

    // Search 'pokemon' in the comics category. const testSearch = { keyword : 'pokemon' , categoryCode : mainCategories . COMICS [ 0 ] } const runTest = async ( ) => { const results = await searchMain...

    深度探索模C++对象模型PDF

    1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态...

    深度探索C++对象模型 超清版

    1.2 关键词所带来的差异(A Keyword Distinction) 关键词的困扰 策略性正确的struct(The Politically Correct Struct) 1.3 对象的差异(An Object Distinction) 指针的类型(The Type of a Pointer) 加上多态...

    node-smmry:smmry.com API的简单包装

    闷闷不乐 ... 入门 安装模块 npm install --save smmry ... SM_KEYWORD_COUNT: Number, // Optional, N the number of keywords to return. SM_WITH_BREAK: Boolean, // Optional, inserts the string [BR

    delphi2-delphi2010 全支持 dcu 装换 pas

    - Supports the following type declarations and their typed consts: * Type redeclarations, for example: type MyTypeString = type String; * All integer types(Byte, Cardinal, Int64, Integer, Longint...

    bunnyhop:基于amqp构建的可插拔微服务消息传递框架

    Here we are not passing in options so it uses the defaults. Notice there is no new keyword. */ const bus = BunnyHop ( 'user' ) // This goes out to every service subscribed to 'event.user.created'. // ...

    boa:用JavaScript调用Python包

    Python简介Boa是Pipcook中的Python桥接层,它使您可以在Node.js中无缝调用Python函数... // prints the pid from python.// using keyword arguments namely `kwargs`os . makedirs ( '..' , boa . kwargs ( { mode : 0

    词法分析代码(c++)

    KEYTABLE keyword[]={{"main",0},{"int",1},{"float",2},{"char",3},{"if",4}, {"else",5},{"for",6},{"while",7},{"do",8},{"switch",9},{"case",10}, {"break",11},{"long",12},{"signed",13},{"unsigned",14},{...

    python3.6.5参考手册 chm

    PEP 468: Preserving Keyword Argument Order New dict implementation PEP 523: Adding a frame evaluation API to CPython PYTHONMALLOC environment variable DTrace and SystemTap probing support Other ...

    C++标准(Standard for Programming Language C++)

    D.4 Implicit conversion from const strings . 1185 D.5 register keyword 1185 D.6 C standard library headers . 1185 D.7 Old iostreams members 1186 D.8 char* streams 1187 D.9 Binders 1196 D.10 auto_ptr ...

    C++ 标准 ISO 14882-2011

    1.7 The C++ memory model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7 1.8 The C++ object model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ...

Global site tag (gtag.js) - Google Analytics