C++ Chapter 1. Accustoming Yourself to C++

原创 2012年04月02日 06:07:09

1. For an object, the definition is where compilers set aside memory for the object. For a function or a function template, the definition provides the code body. For a class or a class template, the definition lists the members of the class or template


Widget w3 = w2;                           // invoke copy constructor!

Fortunately, copy construction is easy to distinguish from copy assignment. If a new object is being defined (such as w3 in the statement above), a constructor has to be called; it can't be an assignment. If no new object is being defined (such as in the "w1 = w2" statement above), no constructor can be involved, so it's an assignment.

Pass-by-value means "call the copy constructor." 

3. Usually, C++ requires that you provide a definition for anything you use, but class-specific constants that are static and of integral type (e.g., integers, chars, bools) are an exception. As long as you don't take their address, you can declare them and use them without providing a definition.

in-class initialization is allowed only for integral types and only for constants.

template<typename T>                               // because we don't

inline void callWithMax(const T& a, const T& b)    // know what T is, we

{                                                  // pass by reference-to-

  f(a > b ? a : b);                                

reference 确保不会make copy, 不用call copy constructor, const确保不会修改原值。

STL iterators are modeled on pointers, so an iterator acts much like a T* pointer. Declaring an iterator const is like declaring a pointer const (i.e., declaring a T* const pointer): the iterator isn't allowed to point to something different, but the thing it points to may be modified. If you want an iterator that points to something that can't be modified (i.e., the STL analogue of a const T* pointer), you want a const_iterator:

6.The purpose of const on member functions is to identify which member functions may be invoked on const objects. Such member functions are important for two reasons. First, they make the interface of a class easier to understand. It's important to know which functions may modify an object and which may not. Second, they make it possible to work with const objects. That's a critical aspect of writing efficient code, because, as Item 20 explains, one of the fundamental ways to improve a C++ program's performance is to pass objects by reference-to-const. That technique is viable only if there are const member functions with which to manipulate the resulting const-qualified objects.

That's because it's never legal to modify the return value of a function that returns a built-in type(You have to use reference or pointer)

7. Initialization List is more efficient than assignment-based version because The assignment-based version first called default constructors to initialize theName, theAddress, and thePhones, then promptly assigned new values on top of the default-constructed ones. All the work performed in those default constructions was therefore wasted. The member initialization list approach avoids that problem, because the arguments in the initialization list are used as constructor arguments for the various data members. In this case, theName is copy-constructed from name, theAddress is copy-constructed from address, and thePhones is copy-constructed from phones. For most types, a single call to a copy constructor is more efficient — sometimes much more efficient — than a call to the default constructor followed by a call to the copy assignment operator.

If in the initialization list, there is no value in the argument, then it will call the default constructor.

8.One aspect of C++ that isn't fickle is the order in which an object's data is initialized. This order is always the same: base classes are initialized before derived classes (see also Item 12), and within a class, data members are initialized in the order in which they are declared. In ABEntry, for example, theName will always be initialized first, theAddress second, thePhones third, and numTimesConsulted last. This is true even if they are listed in a different order on the member initialization list (something that's unfortunately legal). 


A static object is one that exists from the time it's constructed until the end of the program. Stack and heap-based objects are thus excluded. Included are global objects, objects defined at namespace scope, objects declared static inside classes, objects declared static inside functions, and objects declared static at file scope. Static objects inside functions are known as local static objects (because they're local to a function), and the other kinds of static objects are known as non-local static objects. Static objects are automatically destroyed when the program exits, i.e., their destructors are automatically called when main finishes executing.

A translation unit is the source code giving rise to a single object file. It's basically a single source file, plus all of its #include files.

The problem we're concerned with, then, involves at least two separately compiled source files, each of which contains at least one non-local static object (i.e., an object that's global, at namespace scope, or static in a class or at file scope). And the actual problem is this: if initialization of a non-local static object in one translation unit uses a non-local static object in a different translation unit, the object it uses could be uninitialized, because the relative order of initialization of non-local static objects defined in different translation units is undefined.

This approach is founded on C++'s guarantee that local static objects are initialized when the object's definition is first encountered during a call to that function. So if you replace direct accesses to non-local static objects with calls to functions that return references to local static objects, you're guaranteed that the references you get back will refer to initialized objects. As a bonus, if you never call a function emulating a non-local static object, you never incur the cost of constructing and destructing the object, something that can't be said for true non-local static objects.


Things to Remember

  • Manually initialize objects of built-in type, because C++ only sometimes initializes them itself.

  • In a constructor, prefer use of the member initialization list to assignment inside the body of the constructor. List data members in the initialization list in the same order they're declared in the class.

  • Avoid initialization order problems across translation units by replacing non-local static objects with local static objects.

2.1 pass-by-value is generally more efficient than pass-by-reference for built-in (i.e., C-like) types

2.2 Prefer compiler to preprocessor

when use

#define ASPECT_RATIO 1.653

the symbolic name ASPECT_RATIO may never be seen by compilers; it may be removed by the preprocessor before the source code ever gets to a compiler. As a result, the name ASPECT_RATIO may not get entered into the symbol table. This can be confusing if you get an error during compilation involving the use of the constant, because the error message may refer to 1.653, not ASPECT_RATIO.


Two ways to initialize a static const variable in class



static const int aa = 5;


Class Solution



static const int aa;


const int Solution::aa = 5;

Both way works fine, but when we need to use aa as an const in array size, only way 1 works.

There is another way to create a const for array size: enum hack

class GamePlayer {


  enum { NumTurns = 5 };        // "the enum hack" — makes

                                // NumTurns a symbolic name for 5

  int scores[NumTurns];         // fine


it's legal to take the address of a const, but it's not legal to take the address of an enum, and it's typically not legal to take the address of a#define, either. If you don't want to let people get a pointer or reference to one of your integral constants, an enum is a good way to enforce that constraint. 

 'const int' VS 'static const int' VS 'static int?'(inside a class)

In such a context, static declares that there will be only 1 such class-wide data member; as opposed to there being 1 per-instance (inside every object of the class). The const declares that this variable will receive a value only during its construction.

Inside a member function of a class (or for that matter, any function), static means that it's non-automatic; that is, that its value survives returning from the function (also that it can have a value prior to ever entering it, too). It also means that multiple threads of execution through such a routine can contend over access to the variable.

we can only initialize const int in initialization list(also reference variable, because reference can't be assign), while we can initialize static const int in declaration or outside out class by definition
because count is a static variable, the line "static int count = 0;" will only be executed once. Whenever the function is called, count will have the last value assigned to it.
If in class, it can only be initialized outside a class using:
int Solution::s_num = 5;

class Solution
Solution(int s):num_(s)
static int s_num;
static const int num = 5;
int a[num];
//const int _num = 5; error! only static const integral data member can be initialized within a class
//static const int num = 5; correct!
const int num_;
int Solution::s_num = 5
总结:non-static用initialization list初始化, static 在外面初始化

Static class function:
Can be access with a instance of class, can only access static member variable.

2.4  member functions differing only in their constness can be overloaded, 

class TextBlock {



  const char& operator[](std::size_t position) const   // operator[] for

  { return text[position]; }                           // const objects

  char& operator[](std::size_t position)               // operator[] for

  { return text[position]; }                           // non-const objects


   std::string text;


when the two version of function have most part in common, in order to avoid duplication, we can call const function from non-const version using the code below(not vice versa).
class TextBlock {



  const char& operator[](std::size_t position) const     // same as before





    return text[position];


  char& operator[](std::size_t position)         // now just calls const op[]



      const_cast<char&>(                         // cast away const on

                                                 // op[]'s return type;

        static_cast<const TextBlock&>(*this)     // add const to *this's type;

          [position]                            // call const version of op[]





TextBlock's operator[]s can be used like this:

TextBlock tb("Hello");

std::cout << tb[0];                   // calls non-const

                                            // TextBlock::operator[]

const TextBlock ctb("World");

std::cout << ctb[0];                  // calls const TextBlock::operator[]

const member function:
Can't modify any of the object's data members (excluding those that are static and mutable),

these data members may
mutable std::size_t textLength;
mutable bool lengthIsValid; // always be modified, even in}; // const member functions
an array (from the C part of C++) isn't necessarily guaranteed to have its contents initialized, but a vector (from the STL part of C++) is.

the extern keyword is used to tell the compiler that a data object is declared in a different *.cpp or *.c file (code unit). Its required for data objects but optional for function declarations. For example, you have two *.cpp files named A.cpp and B.cpp. B.cpp has a global int that needs to be used in A.cpp. But when a variable or function is defined with keyword "static", it can't be extern to other file, it can only be used in current file.

  1. // A.cpp
  2. #include <iostream>
  3. // other includes here
  4. ...
  5. extern int hours; // this is declared globally in B.cpp
  6. int foo()
  7. {
  8. hours = 1;
  9. }
  1. // B.cpp
  2. #include <iostream>
  3. // other includes here
  4. ...
  5. int hours; // here we declare the object WITHOUT extern
  6. extern void foo(); // extern is optional on this line
  7. int main()
  8. {
  9. foo();
  10. }

Effective C++笔记 【1. Accustoming yourself to C++】

  • colourpen
  • colourpen
  • 2010年10月19日 22:56
  • 320

Conclusion for Accustoming Yourself to C++

条款01: 1.C++是一个同时支持过程形式、面向对象形式、函数形式、泛型形式、元编程形式的语言。 条款02: 1.宁可以编译器替换预处理器 #define ASPECT_RATIO 1.65...
  • tianya_team
  • tianya_team
  • 2015年12月09日 18:15
  • 172

Effective C++ - Accustoming Yourself to C++

前言:如何有效运用C++,包括一般性的设计策略,以及带有具体细节的特定语言特性。知道细节很重要,否则如果疏忽几乎总是导致不可预期的程序行为(undefined behavior)。本文总结对于如何使用...
  • delphiwcdj
  • delphiwcdj
  • 2017年02月04日 21:49
  • 281

EC之Accustoming Yourself to C++

条款01:View C++ as a federation of languages 我们可以把C++看成四部分,即C,Object-Oriented C++,Template C++,STL。 C是...
  • yhjw2bah
  • yhjw2bah
  • 2013年07月28日 09:30
  • 594

Things to Remember: Accustoming Yourself to C++

Effective C++ Third EditionBy Scott Meyers Things to Remember: Accustoming Yourself to C++·         ...
  • arha
  • arha
  • 2005年06月09日 17:49
  • 976

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

Effective C++的学习(Item01-Item05) Item 01:view C++ as afederation of languages 1.     Multi-paradigm ...
  • u014267567
  • u014267567
  • 2017年08月30日 22:11
  • 115

《Effective c++》学习笔记--Accustoming Yourself to C++

Item 01 : View C++ as a federation of languagesC++语言联盟分成4部分 : C Object-Oriented C++封装,继承,多态,虚函数。。。 T...
  • taoyanqi8932
  • taoyanqi8932
  • 2016年10月09日 10:24
  • 251

Chapter 1. C++概述

1.1 C++简介         C++在中国大陆通常被读作“C加加”,而在欧美国家C++通常读作“C plus plus”,该语言的前身是C语言。        1969年美国贝尔实验室的...
  • u014227871
  • u014227871
  • 2014年03月19日 22:11
  • 654

C++ Chapter 1. General(综述)

1.1 Scope 1.2 Normative references 1.3 Terms and definitions(术语和定义) 模板,函数,函数模板,函数模板特殊化,类,类模板,...
  • lzw103
  • lzw103
  • 2016年03月22日 17:11
  • 587

Powershell regular expression.

  • realduke2000
  • realduke2000
  • 2011年05月07日 15:17
  • 1958
您举报文章:C++ Chapter 1. Accustoming Yourself to C++