Monday, December 31, 2012

Thinking in C++ Note

Thinking in C++
  1. Like any human language, C++ provides a way to express concepts.
  2. The stack is an area in memory that is used directly by the microprocessor to store data during program execution. Variables on the stack are sometimes called automatic or scoped variables. The static storage area is simply a fixed patch of memory that is allocated before the program begins to run. Using the stack or static storage area places a priority on the speed of storage allocation and release, which can be valuable in some situations. However, you sacrifice flexibility because you must know the exact quantity, lifetime, and type of objects while you’re writing the program. The second approach is to create objects dynamically in a pool of memory called the heap. In this approach you don’t know until runtime how many objects you need, what their lifetime is, or what their exact type is. Those decisions are made at the spur of the moment while the program is running. If you need a new object, you simply make it on the heap when you need it, using the new keyword. When you’re finished with the storage, you must release it using the delete keyword.
  3. Variables defined outside all functions (with the exception of const in C++) and function definitions default to external linkage. You can specifically force them to have internal linkage using the static keyword. You can explicitly state that an identifier has external linkage by defining it with the extern keyword. Defining a variable or function with extern is not necessary in C, but it is sometimes necessary for const in C++.  In C, the compiler treats a const just like a variable that has a special tag attached that says “Don’t change me.” When you define a const in C, the compiler creates storage for it, so if you define more than one const with the same name in two different files (or put the definition in a header file), the linker will generate error messages about conflicts. The intended use of const in C is quite different from its intended use in C++ (in short, it’s nicer in C++). In C++, a const must always have an initialization value.
  4. This book discusses programming problems, why they are problems, and the approach C++ has taken to solve such problems.
  5. The compilation progress:
 1. Running a preprocessor.
 2. Parses the code to produce a grammar tree.
 3. The code generator walks through the parse tree and generates either assembly language code or machine code for the nodes of the tree.
 4. The linker combines object modules into executable program.

  1. C++ uses static type checking (type checking occurs during compilation instead of the program is running). 
  2. Calling for a void* doesn't clean things up properly. (memory released, but destructor isn't called)
  3. Making a structure nested doesn't automatically give it access to private members. To accomplish this, you must follow like this:   
     struct Holder{<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 
         ... 
         struct Pointer; 
         friend Pointer; 
         struct Pointer{ 
              ... 
         } 
     }

    string.c_str() //produces a pointer to the character.
     delete []myArray;
     const int i[] = {1,2,3,4};<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 
     //!float f[i[3]];// Illegal

C defaults to external linkage for consts while C++ defaults to internal linkage for consts which is very different from all other identifiers in C++. In C, you will get an error if you say:
     const int bufsize = 100;
     char buf[bufsize]; //Because the bufsize occupies storage somewhere, the C compiler cannot know the value at compile time

  1. Temporaries are automatically const.
  2. The use of const inside a class means “This is constant for the lifetime of the object.” However, each different object may contain a different value for that constant. Thus, when you create an ordinary (non-static) const inside a class, you cannot give it an initial value. This initialization must occur in the constructor.
  3.  If you do not provide an initializer for a static variable of a built-in type, the compiler guarantees that variable will be initialized to zero at program start-up. Whenever you design functions containing static variables you should keep multithreadming issues in mind. You can't be sure about the order of initialization of static objects if they're in different files.
  4.  A reference must be initialized when it is created and once a reference is initialized to an object, it cannot be changed to refer to another object.
Good practise for copy-constructor:
  class NoCC {
     int i;
     NoCC(const NoCC&); // No definition
     public:
     NoCC(int ii = 0) : i(ii) {}
  };

  1. During inheritance, everything defaults to private. If the base class were not preceded by public. When an object is created,<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 
 the compiler guarantees that constructors for all of its subobjects are called.  
  1.   In general, we can say that anytime you redefine an overloaded function name from the base class, all the other versions are automatically hidden in the new class. Static  
member functions cannot be virtual. 

A declaration introduces an identifier while a definition allocates storage for the name.   
  If an initializer is present, the declaration is treated as a definition even if the declaration is labeled extern: 
      extern double pi = 3.1416; // definition
Despite the use of extern, this statement defines pi. Storage is allocated and initialized. An extern declaration may include an initializer only if it appears outside a function.
Because we cannot subsequently change the value of an object declared to be const, we must initialize it when it is defined:
    // file_1.cc
      int counter;  // definition
      // file_2.cc
      extern int counter; // uses counter from file_1
      ++counter;          // increments counter defined in file_1
 
Unlike other variables, unless otherwise specified, const variables declared at global scope are local to the file in which the object is defined. The variable exists in that file only and cannot be accessed by other files.
We can make a const object accessible throughout the program by specifying that it is extern:
      // file_1.cc
      // defines and initializes a const that is accessible to other files
      extern const int bufSize = fcn();
      // file_2.cc
      extern const int bufSize; // uses bufSize from file_1
      // uses bufSize defined in file_1
      for (int index = 0; index != bufSize; ++index)
            // ...

The only difference between a class defined with the class keyword or the struct keyword is the default access level: By default, members in a struct are public; those in a class are private.
  //penya01, Dec.19, 2006 Fix star issue 15521605-GP IN ASM_DT.DLL. 
  //1. never use (LPSTR)(LPCSTR)sMediaName, instead should use sMediaName.GetGuffer(0) refer: http://www.codeproject.com/string/cppstringguide2.asp 
  //2. should not use 24, should use 23. or the char array will have no null terminator 
  //3. need initialization 
  memset(pRec->pTapeName,'\0',sizeof(pRec->pTapeName)/sizeof(char)); 
  memcpy (pTapeName , sMediaName.GetBuffer(0), sizeof(pRec->pTapeName)/sizeof(char)-1); 
  sMediaName.ReleaseBuffer();
To  
  memset(pRec->pTapeName,'\0',sizeof(pRec->pTapeName)); 
  strncpy_s(pRec->pTapeName,sizeof(pRec->pTapeName)/sizeof(char),(LPCTSTR)sMediaName, sizeof(pRec->pTapeName)/sizeof(char)-1);  


#include <cstdlib>
using namespace std;
int main(){
 ifstream in("Command.txt");
 string s;
 while(getline(in,s)){
  cout<<s<<endl;
  system(s.data());
 }
 return 0;
}

When static is applied to a function name or to a variable that is outside of all functions, it means “This name is unavailable outside of this file.”
There are two types of linkage: internal linkage and external linkage.
Internal linkage means that storage is created to represent the identifier only for the file being compiled. Other files may use the same identifier name with internal linkage, or for a global variable, and no conflicts will be found by the linker – separate storage is created for each identifier. Internal linkage is specified by the keyword static in C and C++.
External linkage means that a single piece of storage is created to represent the identifier for all files being compiled. The storage is created once, and the linker must resolve all other references to that storage. Global variables and function names have external linkage. These are accessed from other files by declaring them with the keyword extern. Variables defined outside all functions (with the exception of const in C++) and function definitions default to external linkage. You can specifically force them to have internal linkage using the static keyword. You can explicitly state that an identifier has external linkage by defining it with the extern keyword. Defining a variable or function with extern is not necessary in C, but it is sometimes necessary for const in C++.
Automatic (local) variables exist only temporarily, on the stack, while a function is being called. The linker doesn’t know about automatic variables, and so these have no linkage.
In C++, a const must always have an initialization value (in C, this is not true).
Remember that in C and C++, a statement is true if it has a non-zero value, and false if it has a value of zero.
Assigning from a void* is not allowed without a cast in C++ (unlike C), as seen in (3). This is dangerous and requires that programmers know what they’re doing. The static_cast, at least, is easier to locate than the old standard cast when you’re hunting for bugs.
  void* vp = &i;
  // Old way produces a dangerous conversion:
  float* fp = (float*)vp;
  // The new way is equally dangerous:
  fp = static_cast<float*>(vp);

If you want to convert from a const to a nonconst or from a volatile to a nonvolatile, you use const_cast.
One thing you’ll notice is the awkwardness of the use of Structure1 ("struct Structure1 s1;" as it turns out, this is only required by C, not C++). In C, you can’t just say Structure1 when you’re defining variables, you must say struct Structure1. This is where typedef becomes especially handy in C.
arrays cannot be passed by value[32], that is, you never automatically get a local copy of the array that you pass into a function. Thus, when you modify an array, you’re always modifying the outside object. This can be a bit confusing at first, if you’re expecting the pass-by-value provided with ordinary arguments.
CPP = mycompiler
.SUFFIXES: .exe .cpp
.cpp.exe:
        $(CPP) $<
The .SUFFIXES directive tells make that it should watch out for any of the following file-name extensions because they have special meaning for this particular makefile. Next you see the suffix rule .cpp.exe, which says “Here’s how to convert any file with an extension of cpp to one with an extension of exe” (when the cpp file is more recent than the exe file). As before, the $(CPP) macro is used, but then you see something new: $<. Because this begins with a ‘$’ it’s a macro, but this is one of make’s special built-in macros. The $< can be used only in suffix rules, and it means “whatever prerequisite triggered the rule” (sometimes called the dependent), which in this case translates to “the cpp file that needs to be compiled.”
The delete keyword is the complement of new (storage is allocated from the heap), and must be applied to release any storage that is allocated with new (if you forget to use delete, that storage remains unavailable, and if this so-called memory leak happens enough, you’ll run out of memory).
delete []myArray;
When you create a variable on the stack at compile-time, the storage for that variable is automatically created and freed by the compiler. The compiler knows exactly how much storage is needed, and it knows the lifetime of the variables because of scoping. With dynamic memory allocation, however, the compiler doesn’t know how much storage you’re going to need, and it doesn’t know the lifetime of that storage. That is, the storage doesn’t get cleaned up automatically. Therefore, you’re responsible for releasing the storage using delete, which tells the heap manager that storage can be used by the next call to new.
It’s possible in C (but not in C++) to call a function that you haven’t declared.
In fact, object-oriented programming can be summed up in a single phrase: sending messages to objects. Really, that’s all you do – create a bunch of objects and send messages to them.
There are certain issues that you must be aware of in order to organize your code properly and write effective header files. The first issue concerns what you can put into header files. The basic rule is “only declarations,” that is, only information to the compiler but nothing that allocates storage by generating code or creating variables. This is because the header file will typically be included in several translation units in a project, and if storage for one identifier is allocated in more than one place, the linker will come up with a multiple definition error (this is C++’s one definition rule: You can declare things as many times as you want, but there can be only one actual definition for each thing).
This rule isn’t completely hard and fast. If you define a variable that is “file static” (has visibility only within a file) inside a header file, there will be multiple instances of that data across the project, but the linker won’t have a collision[35]. Basically, you don’t want to do anything in the header file that will cause an ambiguity at link time.
The second header-file issue is this: when you put a struct declaration in a header file, it is possible for the file to be included more than once in a complicated program.The preprocessor directives
#define, #ifdef, and #endif<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 
#ifndef HEADER_FLAG 
#define HEADER_FLAG 
// Type declaration here... 
#endif // HEADER_FLAG
don’t put using directives in header files.

protected acts just like private, with one exception that we can’t really talk about right now: “Inherited” structures (which cannot access private members) are granted access to protected members.
C++ guarantees that when an object is created, it is simultaneously initialized. This ensures that you will have no uninitialized objects running around in your system. C doesn’t care
The default constructor is so important that if (and only if) there are no constructors for a structure (struct or class), the compiler will automatically create one for you.
You might think that the compiler-synthesized constructor should do some intelligent initialization, like setting all the memory for the object to zero. But it doesn’t – that would add extra overhead but be out of the programmer’s control. If you want the memory to be initialized to zero, you must do it yourself by writing the default constructor explicitly.
The idea of an overloaded function is that you use the same function name, but different argument lists. Thus, for overloading to work the compiler must decorate the function name with the names of the argument types.
you can use the same function name for different functions as long as the argument lists are different. The compiler decorates the name, the scope, and the argument lists to produce internal names for it and the linker to use.
If the functions have very different behaviors, it doesn’t usually make sense to use default arguments (for that matter, you might want to question whether two functions with very different behaviors should have the same name).
There are two rules you must be aware of when using default arguments. First, only trailing arguments may be defaulted. That is, you can’t have a default argument followed by a non-default argument. Second, once you start using default arguments in a particular function call, all the subsequent arguments in that function’s argument list must be defaulted (this follows from the first rule).
Default arguments are only placed in the declaration of a function (typically placed in a header file). The compiler must see the default value before it can use it. Sometimes people will place the commented values of the default arguments in the function definition, for documentation purposes
void fn(int x /* = 0 */) { // ...
The idea is that you might want to change the function definition to use the placeholder later, without changing all the code where the function is called. Of course, you can accomplish the same thing by using a named argument, but if you define the argument for the function body without using it, most compilers will give you a warning message, assuming you’ve made a logical error. By intentionally leaving the argument name out, you suppress this warning.
More important, if you start out using a function argument and later decide that you don’t need it, you can effectively remove it without generating warnings, and yet not disturb any client code that was calling the previous version of the function.
Your primary concern should be that the interface makes sense to those who use it and who read the resulting code.
As a guideline, you shouldn’t use a default argument as a flag upon which to conditionally execute code. You should instead break the function into two or more overloaded functions if you can. A default argument should be a value you would ordinarily put in that position. It’s a value that is more likely to occur than all the rest, so client programmers can generally ignore it or use it only if they want to change it from the default value.
Because of subtle bugs that the preprocessor might introduce, you should always use const instead of #define value substitution.
A const in C++ defaults to internal linkage; that is, it is visible only within the file where it is defined and cannot be seen at link time by other translation units. You must always assign a value to a const when you define it, except when you make an explicit declaration using extern
extern const int bufsize;
Normally, the C++ compiler avoids creating storage for a const, but instead holds the definition in its symbol table. When you use extern with const, however, you force storage to be allocated (this is also true for certain other cases, such as taking the address of a const). Storage must be allocated because extern says “use external linkage,” which means that several translation units must be able to refer to the item, which requires it to have storage.
In the ordinary case, when extern is not part of the definition, no storage is allocated. When the const is used, it is simply folded in at compile time.
It’s possible to use const for aggregates, but you’re virtually assured that the compiler will not be sophisticated enough to keep an aggregate in its symbol table, so storage will be allocated. In these situations, const means “a piece of storage that cannot be changed.” However, the value cannot be used at compile time because the compiler is not required to know the contents of the storage at compile time. In the following code, you can see the statements that are illegal:
In fact, whenever you’re passing an address into a function, you should make it a const if at all possible. If you don’t, you’re excluding the possibility of using that function with anything that is a const.
As with v( ), the value returned by w( ) is valid after the function returns only because it is static. You never want to return pointers to local stack variables because they will be invalid after the function returns and the stack is cleaned up. (Another common pointer you might return is the address of storage allocated on the heap, which is still valid after the function returns.)
In C it’s very common to pass by value, and when you want to pass an address your only choice is to use a pointer[43]. However, neither of these approaches is preferred in C++. Instead, your first choice when passing an argument is to pass by reference, and by const reference at that. To the client programmer, the syntax is identical to that of passing by value, so there’s no confusion about pointers – they don’t even have to think about pointers. For the creator of the function, passing an address is virtually always more efficient than passing an entire class object, and if you pass by const reference it means your function will not change the destination of that address, so the effect from the client programmer’s point of view is exactly the same as pass-by-value (only more efficient).
Inside a class, const partially reverts to its meaning in C. It allocates storage within each object and represents a value that is initialized once and then cannot change. The use of const inside a class means “This is constant for the lifetime of the object.” However, each different object may contain a different value for that constant.
Thus, when you create an ordinary (non-static) const inside a class, you cannot give it an initial value. This initialization must occur in the constructor, of course, but in a special place in the constructor.
 There is one feature of static const when used inside classes which is a bit unusual: you must provide the initializer at the point of definition of the static const. This is something that only occurs with the static const; as much as you might like to use it in other situations it won’t work because all other data members must be initialized in the constructor or in other member functions.
You can see that a const member function is safe to call with both const and non-const objects. Thus, you could think of it as the most general form of a member function (and because of this, it is unfortunate that member functions do not automatically default to const). Any function that doesn’t modify member data should be declared as const, so it can be used with const objects.

There are two problems with the use of preprocessor macros in C++. The first is also true with C: a macro looks like a function call, but doesn’t always act like one. This can bury difficult-to-find bugs. The second problem is specific to C++: the preprocessor has no permission to access class member data. This means preprocessor macros cannot be used as class member functions.
Any function defined within a class body is automatically inline, but you can also make a non-class function inline by preceding it with the inline keyword. However, for it to have any effect, you must include the function body with the declaration, otherwise the compiler will treat it as an ordinary function declaration.
It is important to understand that an inline is just a suggestion to the compiler; the compiler is not forced to inline anything at all. A good compiler will inline small, simple functions while intelligently ignoring inlines that are too complicated.

In both C and C++ the keyword static has two basic meanings, which unfortunately often step on each other’s toes:
  1. Allocated once at a fixed address; that is, the object is created in a special static data area rather than on the stack each time a function is called. This is the concept of static storage.
  2. Local to a particular translation unit (and local to a class scope in C++, as you will see later). Here, static controls the visibility of a name, so that name cannot be seen outside the translation unit or class. This also describes the concept of linkage, which determines what names the linker will see.
 
Destructors for static objects (that is, all objects with static storage, not just local static objects as in the example above) are called when main( ) exits or when the Standard C library function exit( ) is explicitly called. In most implementations, main( ) just calls exit( ) when it terminates. This means that it can be dangerous to call exit( ) inside a destructor because you can end up with infinite recursion. Static object destructors are not called if you exit the program using the Standard C library function abort( ).
A static member function cannot access ordinary data members, only static data members. It can call only other static member functions.
Your normal habit when passing an argument to a function should be to pass by const reference.
In C and C++, arguments are first pushed on the stack from right to left, then the function call is made. The calling code is responsible for cleaning the arguments off the stack.
 

There are certain rules when using references:
  1. A reference must be initialized when it is created. (Pointers can be initialized at any time.)
  2. Once a reference is initialized to an object, it cannot be changed to refer to another object. (Pointers can be pointed to another object at any time.)
  3. You cannot have NULL references. You must always be able to assume that a reference is connected to a legitimate piece of storage.

1. Global variables are defined outside all function bodies and are available to all parts of the program (even code in other files). Global variables are unaffected by scopes and are always available (i.e., the lifetime of a global variable lasts until the program ends). If the existence of a global variable in one file is declared using the extern keyword in another file, the data is available for use by the second file. Here’s an example of the use of global variables.
2. static
The static keyword has several distinct meanings. Normally, variables defined local to a function disappear at the end of the function scope. When you call the function again, storage for the variables is created anew and the values are re-initialized. If you want a value to be extant throughout the life of a program, you can define a function’s local variable to be static and give it an initial value. The initialization is performed only the first time the function is called, and the data retains its value between function calls. This way, a function can “remember” some piece of information between function calls.
You may wonder why a global variable isn’t used instead. The beauty of a static variable is that it is unavailable outside the scope of the function, so it can’t be inadvertently changed. This localizes errors.
The second meaning of static is related to the first in the “unavailable outside a certain scope” sense. When static is applied to a function name or to a variable that is outside of all functions, it means “This name is unavailable outside of this file.” The function name or variable is local to the file; we say it has file scope.
3.
Automatic (local) variables exist only temporarily, on the stack, while a function is being called. The linker doesn’t know about automatic variables, and so these have no linkage.
Internal linkage means that storage is created to represent the identifier only for the file being compiled. Internal linkage is specified by the keyword static in C and C++.
External linkage means that a single piece of storage is created to represent the identifier for all files being compiled. The storage is created once, and the linker must resolve all other references to that storage. Global variables and function names have external linkage. 
4.
A volatile variable is always read whenever its value is required, even if it was just read the line before.
5.
If you want to convert from a const to a nonconst or from a volatile to a nonvolatile, you use const_cast.
If you take the address of a const object, you produce a pointer to a const, and this cannot be assigned to a nonconst pointer without a cast.

No comments:

Post a Comment