Skip to main content

  | मौसम…

411 समाचार
Public archive edition · Attributed source reporting with original dates · AI drafts are excluded

411 REFERENCE · Wikibooks

C++ Programming/Lost Bits

Reference material by Wikibooks contributors. This retains its source identity and is not 411 news reporting.

Streams "safe bool" idiom or Why define an operator void*() cast operator rather than an operator bool()? This is so that we cannot write things like: int foo = std::cin; or, more importantly, int bah; std::cin << bah; // observe: << instead of >> by mistake. However, it is not perfect, as it allows other mistakes such as delete std::cin; though fortunately such errors are less likely, as delete should be used carefully in any case. The state of the art would have us instead define a private nested class dummy within std::ios, and return a pointer-to-member-function of dummy -- hence allowing implicit conversion from that to bool, but not allowing many other operations. This is sometimes referred to as the "safe bool" idiom, and is motivated by the fact that C++'s bool type has implicit conversions both to and from int as a result of the standardization process. "safe bool" idiom can probably be more clear or have linking to other relevant information if available. auto The auto keyword used to have a different behavior, but in C++ it allows one to omit the type of a variable and let the compiler decide. This is particularly useful for generic programming in which the return type of a function may depend on the type of its arguments. Thus, rather than this: int x = 42; std::vector<double> numbers; numbers.push_back(1.0); numbers.push_back(2.0); for(std::vector<double>::iterator i = numbers.begin(); i != numbers.end(); ++i) { cout << *i << " "; } we could write this: auto x = 42; // We can use auto on base types... std::vector<double> numbers; numbers.push_back(1.0); numbers.push_back(2.0); // But auto is most useful for complicated types. for(auto i = numbers.begin(); i != numbers.end(); ++i) { cout << *i << " "; } Scope with source examples The concept of scope is straightforward unless procedures are included in the mix; then it becomes more difficult to follow: Confusing Scope The first variable 'i' is put out of scope in two separate sections. Thus the repeated statement cout << i << ' '; means something very different each time it is written. The 'i' referred to is a different location in memory on each occasion. This is what was meant by `context' in the introduction: the context or background in which the statement is placed of is different each time, so the statement does something different in each place. There are important things to note about the above example. The program is only an example and unusually convoluted, it is useful to demonstrate the idea of scope and little else. While it illustrates the concept of scope, it fails to illustrate usefully the purpose of scope. The purpose of Scope Some variables are required to store information for an entire program, while other variables are short-term variables which are brought into existence momentarily for a single small purpose and then disposed of, by going out of scope. In the following program, an array of numbers is read in and then a procedure is called that computes the average of the numbers in the array. Within the procedure, in order to move through the array and select the elements in the array in turn, a variable 'i' is created for that one purpose. Contrast the two kinds of variable: the array itself, which is in scope throughout the entire program, and the variable 'i' which is in scope only for a small section of the code, to do its own little job. Scope and control structures Within a single procedure it is possible to begin a new level of scoping. In fact it occurs every time a left brace `{' is written and it ends where its matching right brace '}' is written. Thus layers of scope to any depth can be built up as can be seen in the following program. The following program has four levels of scoping. The innermost level is said to be enclosed by the levels around it, thus we talk about inner levels and enclosing levels of scoping. Again this program is for illustration purposes only and does nothing of real value. The output if this program is 6 5. To understand why, we look first at the simpler situation of 'i', and we see why a five is printed for it, and then next at the more complicated situation with 'j' and why a six is printed for it. A new variable 'i' is created at each new level of scope. Thus only the first assignment to 'i', where 'i' is assigned the value of five, affects this particular variable 'i': the variable that is printed. That variable does not alter its value after that first assignment and so the final statement prints a five. The other assignments to 'i' are irrelevant to the final print statement. In contrast, the variable 'j' is created only once, hence the assignment where `j' is assigned the value of six, alters this only existing variable called 'j' even though the variable is declared at an enclosing level of scope. If a program has a scope level inside another, and no variable of the right name is declared at this inner level, then the computer `looks outwards' to the next enclosing level of scope. If there is no variable of that name declared there either, then it will look out further and again further outwards until the variable's declaration is found. (Of course, if a declaration for the variable is never found then the compiler indicates an error, stating that the variable is undeclared and so the program is not compiled.) Scope using other control structures Above we stated that a new level of scope started with each left brace `{'. However, it is not common to use just a naked left brace: usually the left brace is associated with an if statement or a while statement or some such. We add these to the above program to make the more usual (but still useless) example program following. The program does compile and it prints a 5 when it runs, but does little of value as a program. We added an extra level of scoping at the switch statement because this statement demands a left brace, and it shows that even at that point a new level of scope is opened (because we were able to declare yet another variable called `i' without getting an error). As you can see, the various control structures (i.e. the while, if and switch statements) all end at their own matching right brace and hence at the same point as the scope ends. It is fair to say that each of these control statements operates over an area of scope. But remember, scope is a concept about variable names and the area in which they are defined, not control structures. It is not essential that either the if or the while statements have an opening brace following, and program average above shows an example of this with its while statement. In this situation, no new level of scope is begun. It is the left brace that opens the new level of scope, not the if or while statement itself. The switch statement demands a left brace at that point, but notice that the `i' switch variable is at the old level of scope. The new level of scope comes into existence immediately following the left brace as always. For all practical purposes, the for loop control structure can be seen to have scoping that operates in the same manner. However it is permissible to declare the for loop variable within the for statement itself, as can be seen in line eight of program average above. This is good programming practice as it makes the structure of the program clearer. With all the programs in this section the statements start further and further to the right as the level of scope deepens. This is referred to as indentation and is a very important feature of program presentation. It makes the scope level explicit at all times and also makes it clear where a statement ends. For example, in the above program the line cout << j << ' '; is within the while loop whereas cout << i << endl; is outside that loop. The loop and the scope level end at the same point: the right brace between these two statements signals the end of both of these. The scoping of the for control statement in detail This subsection is probably more confusing than useful, but it is offered for completeness; feel free to skip it. The for control statement has an unusual scoping, in that the left round bracket also starts its own level of scope. Thus the following program is legal: and it gives the output: 1 -1 2 -1 3 -1 4 -1 5 -1 6 -1 7 -1 8 -1 9 -1 5 This special feature of the for statement is not shared by, for example, the while statement. It is a syntax error to attempt to declare a variable within the while statement, so while(int i < 22)i++; gives a syntax error. This special scope level enables one to declare a for loop variable within the for loop itself (like the variable 'i' in the above program), instead of having to declare it in the enclosing scope level, creating a neater program. But it is a little peculiar. The above program does show one interesting feature: in order to check if a new level of scope has been opened, it is only necessary to attempt to declare an existing variable again at that level, as was done with the variable `i' in the above example program, which has a new variable `i' declared at every level possible. The above program also illustrates one further very important point: there is a saying in computer programming that is it possible to write bad code in any language. The above program is quite unclear in its operation and a good example of bad coding: it is good code to illustrate a point, but bad code to read. All code should be written to make the program as clear as possible as discussed elsewhere under the topic of program style. Scope and lifetime The scope of a variable should be contrasted with its lifetime. In the program above called `Confusing Scope Program' the first variable `i' goes out of scope for a time but it remains in existence, thus its lifetime is continuing while it is out of scope. In older programming languages, it is difficult to contrive examples where scope and lifetime are different - in general in these older languages the two are the same, so lifetime equals scope. Not only is it difficult, it is not all that useful in the general case when it does occur. In recently created computer languages like C++ however, the idea of having variables that are out of scope but still alive is heavily exploited and creates the principle distinguishing feature of C++: the C++ class. This is the above program re-written with a class: In this version of the program, the variables `length' and `aa' are alive after the class `sp' comes into existence. However, their scope has been limited: they are alive but out of scope, storing the information but not being directly available in the main program. Keeping variables out of scope in this manner is very helpful in debugging a program, by narrowing the number of lines in which the variable in question can possibly change its value. evolve and add references to the further insight and practical usefulness in sections like class space. C++ Programming strcat_s strcat_s function proposed for close replacement of strcat function . strcat_s have an additional argument than strcat which specifies what will be the maximum size of destination string. strcat_sfunction appends characters of the source string to the end of first string destination string #include <string.h> errno_t strcat_s(char * dest,rsize_t s1max,const char * scr); for example : char str1 , str2; printf( "Enter your first string : " ); scanf( "%s", str1 ); printf( "Enter your second string: " ); scanf( "%s", str2); strcat_s(str1, 16, str2); printf( " %s\n", str1 ); It would be probably acceptable to include a link to the standard strcat() function, and make a special section regarding particularities of the Microsoft C Runtime Library and some other C libraries. At this time there is not enough content or displayed interest in doing so. .