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++ 读书笔记之Part1.Accustoming Yourself to C++

1、View C++ as a federation of languages C++的四个次语言: 1)C 2)Object-Oriented C++ 3)Template C++ ...

(Effective C++)第一章 让自己习惯C++(View Yourself to C++)

1.1 条款1:视C++为一个语言联邦(View C++ as a federation of language) C++主要的次语言(sublanguage): l  【3-1-1】 说到底C+...
  • wzhwho
  • wzhwho
  • 2011年10月15日 19:33
  • 563

Qt5官方demo解析集16——Chapter 2: Connecting to C++ Methods and Signals

本系列所有文章可以在这里查看http://blog.csdn.net/cloud_castle/article/category/2123873 接上文Qt5官方demo解析集15——Chapter...

Data Structures and Other Objects Using C++ (Chapter 1) 学习笔记二

Preconditions and Postconditions(先决条件和后置条件)     When you are using a function, you only need to thin...

『C++ Primer学习笔记』Chapter 1

概括1.1. 编辑器、编译器和集成了编译器的IDE的区别;使用DOS命令行语句调用不同的编译器编译源文件和设置支持C++11的参数;1.2. iostream库中的cin和cout的使用;1.3. 单...

重温C++ —— Chapter 1&2 变量和基本类型

Chapter 2 变量和基本类型 C++的主要设计目标之一就是允许程序员自定义类型,而且这些类型和内置类型一样易于使用。 掌握C++的第一步是学习语言的基本知识和标准库。 ...
  • swgshj
  • swgshj
  • 2014年06月12日 14:12
  • 530

Chapter 1 Hello, world of concurrency in C++!

Summary In this chapter, I covered what is meant by concurrency and multi-threading and why you’d ch...

C++ Primer Plus 第六版_编程练习(4)(Chapter_five 1-5)

编程工具用得好,搞起研究事半功倍。导师的意见是,学好C++,其他编程都不怕。暂时没有迫切的实战需要,于是决定从最基础的学起,挑了《C++ Primer Plus (第六版)》这本书,开始啃吧。编程练习...

Learning C++ by Creating Games With UE4(15.05.20)(Chapter 11-1)Monster

Chapter11-1 怪物   我们这一章节需要在场景中添加一个岛屿的场景作为范例。玩家将可以在整个岛上漫游,同时他也会遇到一些敌人,NPC可以在他遇到敌人之前给予他一定帮助和建议   岛屿...
您举报文章:C++ Chapter 1. Accustoming Yourself to C++