现在的位置: 首页 > 综合 > 正文

effective c++ 学习笔记之 Shifting from c to c++

2013年03月29日 ⁄ 综合 ⁄ 共 4885字 ⁄ 字号 评论关闭
Item 1:  Prefer const and inline to #define

  I--- why? const advantage?
   1. because #define is not part of language prese; eg #define ASPECT_RATIO 3.1345  ,ASPECT_RATIO will be removed by the processor before entered into compiler.
   2. about const trick
        NOTE: const char * const myName ="shuzjd";
  
  when we need the value of a class constant during  compilation of the class. Using enum hack technique.This  take advantage of the fact that the value of an enumerated type can be used where ints are expected.
      class GamePlayer{
           private:
                    enum {NUM_PLAYER =6};
            int scores[NUM_PLSYER];}

  II---using inlinde rather than #define
     eg:   #define max(a,b)  ( (a)>(b)? (a):(b))
         1.           inline int max(int a,int b){ return a>b ? a: b;}
          2.    eg1. is not quite the same as the macro above,because this version of max can only be called with ints,but a template fixes thet problem quite nicely:
                 template<class T>
                    inline const T &max(const T& a,const T& b){ return a>b ? a: b;}
           
        Given the availability of const and inlines, the need for preprocessor is reduced, but it's not completely eliminated.
        Because #inclued #ifdef ...#ifndef #endif to play important roles in controlling compilation.


Item2: Prefer<iostearm> to <stdio.h>

   type safety and extensibility are cornerstones of the c++ way of life.

Item3:use const whenever possible
  a. const modify variables(int or pointer)
   char *str="greeeting"; //non-const data; non-const pointer
   const char *str="hello"; //const data;non-const pointer;
   const char* const str ="shuzjd"; const data;const pointer;
   
  STL iterators are modeled on pointer.   
           iterator likes a T* pointer;
   
         std::vector<int>  ivec;
         I...const  std::vector<int>::iterator iter = ivec.begin() ; // like T* const;
               *ivec=10;
                        ivec++;//error,iter is const;
         2...    std::vector<int>::const_iterator cIter=
                 vec.begin();
                   *ivec=10;
                        ivec++;//right,  data is const,ivec can change.
    b.const modify function
         1.const used to  return a constant value; it can reduce the client errors.
            eg:
               class Rational{... };
             const  Rational operator* (const Rational& lhs,const Rational& rhs);
                       Q:why result of operator * be a const object?
                            A: Because if it weren't,clients would be able to make mistake like this:

                      if( a*b=c)//use const can be able to quickly find the error ,because  a*b is const that  can't be assignment.

     c. const member funcitons
             why use that? 
                        It's important to know which funtions modify an object and which may not.


Item 4: Make sure that objects are initialized before they're used.
         For non-member objects of built-in
types. Need to do this manually.
                For example:
                          1. int x=0; //manual  initialization of an int.
                          
                          2.  double d;      //"initialization" by reading from
                                std::cin>>d;  //input stream.
                           
         The responsibility for initialization falls on constructors. Rule: make sure--all constructors initialize everything in object.
              But not to confuse assignment with initialization.

             example: Consider a constructor for a class representing entries in an address book
                    code:
                             class PhoneNum{...};
                             class ABEntry{
                                       private:
                                                 std::string theName;
                                                 std::string theAddress;
                                                 std::list<PhoneNum> thePhones;
                                                 int numTimesConsulted;
                                        ABEntry(const std::string&name, const std::string& address,const std::list<PhoneNum> phone);
                              }

ABEntry::ABEntry(const std::string& name, const std::string& address,

                 const std::list<PhoneNumber>& phones)

{

  theName = name;                       // these are all assignments,

  theAddress = address;                 // not initializations

  thePhones = phones

  numTimesConsulted = 0;

}

A better way to write the ABEntry constructor is to use the member initialization list instead of assignments:

ABEntry::ABEntry(const std::string& name, const std::string& address,

                 const std::list<PhoneNumber>& phones)

: theName(name),

  theAddress(address),                  // these are now all initializations

  thePhones(phones),

  numTimesConsulted(0)

{}                                      // the ctor body is now empty

sometimes must be used to initial. For example,data members that are const or are references
    
   the relative order of initialization of non-local static objects defined in different
translation units is undefined
.
     How to elimination the problem that caused by non-local static objects defined in different translation units?
               A:  Move each non-local static object into its own function.And declared static.These
functions return references to the objects they contain. Non-local static objects are replaced with local static objects.
 

    

Here's the technique applied to both tfs and tempDir:

class FileSystem { ... };           // as before



FileSystem& tfs()                   // this replaces the tfs object; it could be

{                                   // static in the FileSystem class



  static FileSystem fs;             // define and initialize a local static object

  return fs;                        // return a reference to it

}



class Directory { ... };            // as before



Directory::Directory( params )      // as before, except references to tfs are

{                                   // now to tfs()

  ...

  std::size_t disks = tfs().numDisks();

  ...

}



Directory& tempDir()                // this replaces the tempDir object; it

{                                   // could be static in the Directory class



  static Directory td;              // define/initialize local static object

  return td;                        // return reference to it

}



         
       

抱歉!评论已关闭.