Effective C++的学习(Accustoming Yourself to C++)

来源:互联网 发布:淘宝流量充值怎么开店 编辑:程序博客网 时间:2024/06/06 02:24

Accustoming Yourself to C++

Item 01:view C++ as afederation of languages

1.     Multi-paradigm programminglanguage: procedural

Object-oriented

Functional

Generic

Metaprogramming

2.     The four sub-language:       C

Object-Oriented C++

Template C++

STL

For example: As to the built-in C(C-like),the pass-by-value is more effective than the pass-by-reference, but thepass-by-reference-to-const is more effective in Object-Oriented C++, which isthe same as Template C++. However, when you enter the scope of STL, thepass-by-value gets better again.

Item 02:Preferconsts, enums and inlines to #defines

1.     Use consts to reduce theamount of object code, because the  “#define”will replace the allmacros with the values behind  #define.

2.     In header file, the pointer should be defined as constantpointer, because it will be included by many other files. Meanwhile, if it is achar pointer, using string to replace it is better. For example,

const std:: string authorName(“Scott Meyers”);   is better than 

const char* const authorName = “Scott Meyers”;

3.     #define have no encapsulation(封装性).

4.     The const in class

#include <iostream> class GamePlayer{public:   GamePlayer(constint a):NumTurns(a)   {}private:   const int NumTurns;   //int scores[NumTurns]; }; int main(){   GamePlayer gameplay(3);   return 0;}

In general, C++ demands anything you will use to bedefined. But if it is class 的专属常量 又是static 且是整数类型(integraltype, such as ints, chars, bools),则可以特殊处理,你可以使用它们而不需要提供定义。

only static const integral datamembers can be initialized within a class.

#include <iostream> class GamePlayer{public:  /*GamePlayer(constint a):NumTurns(a)  {}*/private:  static const int NumTurns =4;  intscores[NumTurns];                  or enum { NumTurns = 5 };}; int main(){  GamePlayer gameplay();  return 0;}nonintegral type must be given the definition#include <iostream> class GamePlayer{public:private:  static const doubleNumTurns;};const doubleGamePlayer::NumTurns = 4;int main(){  GamePlayer gameplay();  return 0;}


enum and #define both admit to gettheir address, and you sometimes hope nobody use pointer or reference to pointthem.

5.     Use template inline function toreplace macros function as much as possible.

Item 03:Use constwhenever possible.

1.     The location of const. it is atthe right of  “*” to represent constpointer, and non-const data. If at the left, represent const data and non-constpointer, if both, represent const data and const pointer.

2.     In STL, iterator can beregarded as pointer, e.g. T*, so const iterator should be regarded as T* const,and the const_iterator is equal to const T*.

std::vector<int>vec;vec.push_back(3);vec.push_back(2); conststd::vector<int>::iterator iter =vec.begin();iter++;  // error!*iter = 10;std::vector<int>::const_iteratorciter = vec.begin();citer++;*citer = 10; //error!return 0;


3.     Consider using const limit thereturn parameter in function. e.g. operator * ,if you do not add the const tolimit return parameter, the following situation will happen:

Rationala = 10, b(a);std::cout<<a*b<<std::endl;const Rational c = 1;if((a*b)= c)      this case will be regarded as correct.Obviously, it is not the programmer’s intention. class Rational{public:  Rational(constdouble& data):cdata(data)  {      this->data= data;  }  Rational():cdata(data){}  Rational(constRational& rational):cdata(data)  {      this->data= rational.data;  }public:  const Rationaloperator* (constRational& lhs)  {      this->data*= lhs.data;      return *this;  }   constRational& operator = (const Rational& raltional)  {      this->data= raltional.data;      return *this;  } public:  const double& cdata;private:  double data;};  std::ostream& operator<<(std::ostream& out, constRational& rational)  {      out<<rational.cdata;      returnout;  }int main(){  Rational a = 10, b(a);  std::cout<<a*b<<std::endl;  const Rationalc = 1;  std::cout<<((a*b) = c)<<std::endl;  return 0;}


4.     There are the following pointsin the code above need to be noticed:

1)     Friend function: it is not apart of class, but can use the members in the class.

2)     In the same class, we can visitthe private members in objects of the class. For example:

 

  constRational& operator = (const Rational& raltional)   {      this->data= raltional.data;      return *this;   }

3)     The cout is the object ofostream, if we want it to output our classes, the return parameter ofoverloaded function of “<<” should not be limited by const and shouldreturn ostream object. Otherwise, successive “<<” will be not able to beused. E.g.

std::cout<<a*b<<std::endl;

5.     We can overload functions accordingto the constness of member functions.

const char& operator[](std::size_t position) const{    returntext[position];}char& operator[] (std::size_t position){    returntext[position];}


Note:As to non-const function above, the “&” must be maintained to make themember “text” be able to be assigned.

6.     In the const class, constfunctions will be called automatically to ensure that the members in constclass are not modified. Meanwhile, in Microsoft visual C++, non-const objectcan call const member functions, but the const object can only call constmember functions.

7.     Const member functions can’tmodify the members in the class, but can modify the members that are signed by “mutable”.

 

 std::size_t length() const;private:  char* text;  mutablestd::size_t textLength;  mutable bool lengthIsValid;};std::size_tTextBlock::length() const{  if(!lengthIsValid)  {     textLength = std::strlen(text);     lengthIsValid = true;  }  returntextLength;}

8.     When const member function isthe same as non-const member function on the implementation, we can usenon-const member functions to call const member functions to reduce codes.

 

   const char& operator[](std::size_t position) const    {       returntext[position];    }    char& operator[] (std::size_t position)    {       return const_cast<char&>(static_cast<constTextBlock&>(*this)[position]);    }

              Note:const_cast to cast the const and transforms the “const char&” to “char&”.The static_cast transforms the “*this” into “const TextBlock&”, and callthe member “[]”.

Item 04:Make surethat objects are initialized before they’re used.

1.     In C part of C++, ifinitialization may bring cost in the running, it will be not ensured to beinitialized. But in the non-C parts of C++, its rules are different from the Cpart of C++. This also explains the reason why the array from C part of C++does not ensure its content to be initialized but vector can do it. To solvethe problem, we only need to initialize every variable before it is used.

2.     The classes that are defined byusers are initialized by constructors, which ensure each member to be initialized.

3.     The assignment andinitialization are different. As to the built-in members, these two operators’costs are equal, but to classes defined by users, their costs are different. e.g.

class PhoneNumber{public:PhoneNumber():number(0){}PhoneNumber(constint& num){    number = num;}PhoneNumber(constPhoneNumber& PNumber){    number = PNumber.number;}constPhoneNumber& operator = (const PhoneNumber& pNumber){    number = pNumber.number;    return *this;}private:int number;};class ABEntry{public:ABEntry(conststd::string& name, const std::string&address, const PhoneNumber& phone): theName(name),theAddress(address),thePhone(phone){               //theName = name;              //theAddress =address;              //thePhone =phone;    numTimesConsulted = 0;}private:std::string theName;std::string theAddress;//std::list<PhoneNumber>thePhone;PhoneNumber thePhone;intnumTimesConsulted;};int main(){std::string name = "yang";std::string address = "hubei";PhoneNumber phones(10);ABEntry entry(name,address,phones);


       Note:the assignment is to call assignment operator, and the initialization is tocall constructors. The constructors initializing members in the class must use memberinitialization list but not assignment in constructors. The former is moreeffective than the latter because the former directly call the copyconstructors but the latter need to call default constructor and copyassignment operator(=). The default constructor is called at the moment ofrunning the equation.

4.     C++ rules: The initializationof members in the objects must be done before entering the constructors.

5.     The members restricted by constor references must be initialized in member initialization list.

6.     When both of the members andconstructors are too many, we can select those members whose performance inassignment is equal in initialization(e.g. built-in members) to place aninitialization function(private) and then to be call by each constructor.

7.     The order in memberinitialization list should be coincident with the declaration order in theclass. Because compiler constructs these members by the order.

8.     The initialization order ofnon-local static objects in different translation unit:

1)     Translation unit: those sourcecodes in single object file, including the single object file and its headerfiles.

2)     The non-local static objects,like global variables, variables in namespace, and the variables in class,function, and file are stated as static objects.

3)     If the non-local static objectsare called without initialization, the procedures will break out. However wecan use local static objects to replace the non-local static objects.

4)     During the function is called,if the static objects firstly are encountered, the compiler will initializethese objects. Notice: A. static objects will be valid until the end; B. if thestatic object is not encountered, it will not be initialized, and in otherwords that will not trigger the constructors and destructors.

FileSystem&tfs(){staticFileSystem fs;return fs;}int main(){for(int i=0; i<3; i++){     tfs().count();     std::cout<<tfs().numDisks()<<std::endl;}

Note: theresults of the codes are 1, 2 and 3, which denotes the fs have been initializedand only once, and its memory is all saved the way until the end.

Item 05: know what functions C++ silently writes andcalls.

1.     If you define an empty class,the compiler will write copy constructor, default constructor, destructor andcopy assignment operator for you. E.g.

class Empty{};class Empty{   Empty(){...}   Empty(constEmpty& rhs){...}   ~Empty(){...}   Empty& operator= (const Empty& rhs){...}};


2.     When you have definedconstructors including destructors, copy constructor, destructors withparameters est. compiler will not provide default constructor for your class.

3.     Transmitting built-inparameters by reference, compiler require us to use “const”, because if we useconstant parameters(e.g.3, 3.4 etc) to call functions where “consts” are notused, contradiction will occur owe to the parameters are not able to modifiedbut they are not “const” parameters.

template<class T>class NameObject{public:    NameObject(std::string& name, const T& value);    NameObject& operator=(const NameObject& object);private:    std::string& nameValue;    const TobjectValue;};template<class T> NameObject<T>::NameObject(std::string&name, const T&value):nameValue(name),objectValue(value){}template<class T>NameObject<T>& NameObject<T>::operator=(const NameObject<T>& temp){    return *this;}int main(){    std::string newDog("Persephone");    std::string oldDog("Satch");    NameObject<int>p(newDog, 2);    NameObject<int>s(oldDog, 36);     p = s;


Note: if there are the following cases in class, the compiler couldnot provide copy assignment operator(=):

1)     Contain reference members;

2)     Contain const members;

3)     Their base classes’ copyassignment operators are declared as private.

















原创粉丝点击