Mysterious c++
  Traps, Pitfalls and Secrets



                          Kent Wang
                          Jun 1, 2012
Why this talk

• 警惕靠巧合编程

• 勿在浮沙筑高台

• 了若指掌方可收放自如

• 见山非山, 见水非水
C++很____
C++很____
简单
C++很____
猜猜我是谁

Foo<T> bar;
猜猜我是谁

Foo<T> bar;

template <typename T>
class Foo {
  ...
};
猜猜我是谁

Foo<T> bar;

template <int T>
class Foo {
  ...
};
猜猜我是谁

Foo<T> bar;


int Foo;
int T;
int bar;
仇者联盟大战超人

Foo<T> bar;


Superman Foo;
Spiderman T;
Ironman bar;
sizeof

class A {   class B {    class C {
};             char c;      virtual void foo();
            };              char c;
                         };
sizeof

class A {       class B {    class C {
};                 char c;      virtual void foo();
                };              char c;
                             };


            1
sizeof

class A {       class B {        class C {
};                 char c;          virtual void foo();
                };                  char c;
                                 };


            1                4
sizeof

class A {       class B {        class C {
};                 char c;          virtual void foo();
                };                  char c;
                                 };


            1                4                  8
Constructor
class Animal {
 public:
   Animal() {
     Animal("Lion", 21);
     Run();
   }

     Animal(const string& name, int age);

     virtual void Run() = 0;
};
Constructor
class Animal {
 public:
   Animal() {
     Animal("Lion", 21);
     Run();
   }

     Animal(const string& name, int age);

     virtual void Run() = 0;
};
颤抖吧! 地球人!
简单
C++很____
C++很____
C++很____
恐怖
C++很____
Function Object


       Member Function pointer                      Temporal Object                       dynamic_cast


 Function pointer
                                  Pass By Reference                Pure Virtual Class       RTTI
                                                                                                   typeid

                    Overloading         Pass By Value                  Pure Virtual Function

Copy Constructor
                              Virtual Function                           Multiple Inheritance
                    Constructor                  Dynamic Binding

                                                                      Inheritance
   Exception
         Destructor
                                  Class                                      Virtual Inheritance
                                                                                                   Friend




                                                          Template
                                              String
                              Adaptor
Namespace
                                    STL
   Operator New       RAII               Iterator      Function Template                    Class Template

                                                               Template Specialization
        Memory Management
                                                          Partial Specialization

 Smart Pointer
                            Reference                  Preprocessor
                                                                           Template Meta Programming
知乎?
•   构造和析构函数机制是如何实现的?

•   函数调用是如何传递及返回对象的?

•   函数重载是如何实现的?

•   多态是如何实现的?

•    常机制是如何实现的?为何我们不用?

•   静态变量是如何初始化的?
Tips 1


           Don't live with
         unknown unknowns
What to talk

• C++语言演化历史

• Object Memory Layout

• 函数调用语义及临时对象

• 静态变量初始化
What NOT to talk
• 语法细节

• 二进制兼容性

• Exception Handling

• Template & Generic Programming

• C++11 (C++0x)
Outline
•   青梅煮酒论英雄

•   天机亦可泄露

    -   对象内存模型

    -   函数转换

    -   函数调用

    -   临时对象
青梅煮酒论英雄
Timeline
                                                            2011
   1980                1989                                 C++11
C with class         CFront 2.0              1992
                                             HP C++    Lambda Expression
   Class        Multiple Inheritance                    Automatic Type
Inheritance       Abstract Class           Exception      Threading




                1983 - 1986              1991             1996
               C++ - CFront 1.1        CFront 3.0       C++ 98/03

               Virtual Function        Template          STL
                  Overloading                          Namespace
                   Reference
C++看起来像是...
C++看起来像是...
缘起

               值语义
零负担



        C兼容性


                惯用法
 编译器隐
 藏操作
C兼容性
• class Foo{};

  - unnamed structure in C

• Header File

• Preprocessor / macros
C兼容性
• class Foo{};

  - unnamed structure in C   struct {
                                int a;
                                int b
• Header File                } foo;

                             foo.a = 10;
• Preprocessor / macros
零负担

• 不对栈变量自动初始化

• Object on Stack

• 默认构造函数不对POD类型进行初始化

• 成员函数默认为非虚函数
值语义

Person kent("kent");

                             kent   "kent"
值语义

Person kent("kent");
Person lazy = kent;      kent       "kent"



                             lazy   "kent"
引用语义

Person kent("kent");

                          kent   "kent"
引用语义

Person kent("kent");
Person lazy = kent;       kent
                                 "kent"
                          lazy
Not very good at OO


• No reflection and dynamic creation

• Object lifetime management

• Complex syntax stops refactoring tools
既然如此,
为什么我们还要用C++
C++ is deterministic
C++ is deterministic
• Destructing is determinate

  - No GC

• Performance is predictable

  - C++ is fast only when coders are experts

  - Java is almost as fast, much higher
    productivity
Where the Focus Is
           Efficiency    Flexibility   Abstraction   Productivity



   C                                   non-goal      non-goal



 C++                                                 non-goal



             at the       at the
Java, C#
           expense of   expense of
Conclusion
• There are only two kinds of languages

  - The ones people always complain about

  - The ones nobody uses

• C++ is an undoubted success

• One language doesn’t fit all

  - Important to known when and when not
天机亦可泄漏
对象内存模型
简单对象

class Animal {
 public:
   void Run();

  private:
   char* name;
   int age;
   char sex;
};
简单对象

class Animal {                name
 public:
   void Run();

  private:                    age
   char* name;
   int age;
   char sex;
};                      Sex    Alignment
单一继承
class Animal {
 public:
   void Run();

  private:
   char* name;
   int age;
   char sex;
};

class Lion : public Animal {
  private:
   char* address;
};
单一继承
class Animal {                       address
 public:
   void Run();

  private:                            name
   char* name;
   int age;
   char sex;
};                                    age

class Lion : public Animal {
  private:
   char* address;              Sex     Alignment
};
虚函数

   class Animal {
    public:
      void Run();
      virtual void Say();

     private:
      char* name;
      int age;
      char sex;
   };


* vptr的偏移量与编译器实现有       .
虚函数

   class Animal {                       vptr
    public:
      void Run();
      virtual void Say();               name

     private:
      char* name;                       age
      int age;
      char sex;
   };                             Sex    Alignment


* vptr的偏移量与编译器实现有       .
vptr and vtbl

      vptr


      name


      age


Sex    Alignment
vptr and vtbl

      vptr         0   type_info    type_info


      name         1     Say       &Animal::Say


      age


Sex    Alignment


                   vtbl$Animal
带虚函数的继承
class Animal {
 public:
   virtual void Run();
   virtual void Say();

  private:
   char* name;
   int age;
   char sex;
};

class Lion {
  public:
   virtual void Say();
};
带虚函数的继承
class Animal {
 public:
   virtual void Run();
   virtual void Say();         vptr

  private:
                               name
   char* name;
   int age;
   char sex;
                               age
};

class Lion {             Sex    Alignment
  public:
   virtual void Say();
};
vptr and vtbl

      vptr


      name


      age


Sex    Alignment
vptr and vtbl

      vptr         0    type_info    type_info


      name         1      Run       &Animal::Run


      age          2      Say        &Lion::Say


Sex    Alignment


                       vtbl$Lion
M o re
• 多重继承

• 带虚函数的多重继承

• 虚继承

• 带虚函数的虚继承

• 多重虚继承
函数转换

 class Animal {
  public:
    void Run();

   private:
    ...
 };

 Animal a;
 a.Run();



* 真实情况下编译器会对函数名称进行编码,即name mangling.
函数转换

 class Animal {
  public:
    void Run();

   private:
    ...
 };

 Animal a;
 a.Run();



* 真实情况下编译器会对函数名称进行编码,即name mangling.
函数转换

 class Animal {                    void Animal_Run(Animal* this)
  public:                          {
    void Run();                      ...
                                   }
   private:
    ...                            Animal a;
 };                                Animal_Run(&a);

 Animal a;
 a.Run();



* 真实情况下编译器会对函数名称进行编码,即name mangling.
函数转换

 class Animal {                    void Animal_Run(Animal* this)
  public:                          {
    void Run();                      ...
                                   }
   private:
    ...                            Animal a;
 };                                Animal_Run(&a);

 Animal a;
 a.Run();



* 真实情况下编译器会对函数名称进行编码,即name mangling.
虚函数转换
class Animal {
 public:
   void Run();
   virtual void Say();

  private:
   ...
};

Animal a;
a.Say();

Animal* p = &a;
p->Say();
虚函数转换
class Animal {              void Animal_ctor(Animal* this)
 public:                    {
   void Run();                this.vptr = &Animal_vtbl;
   virtual void Say();      }

  private:                  void Animal_Say(Animal* this)
   ...                      {
};                          }

Animal a;                   Animal a;
a.Say();                    Animal_ctor(&a);
                            Animal_Say(&a);
Animal* p = &a;             Animal* p = &a;
p->Say();                   (*(p->vptr[1]))(p);
虚函数转换
class Animal {              void Animal_ctor(Animal* this)
 public:                    {
   void Run();                this.vptr = &Animal_vtbl;
   virtual void Say();      }

  private:                  void Animal_Say(Animal* this)
   ...                      {
};                          }

Animal a;                   Animal a;
a.Say();                    Animal_ctor(&a);
                            Animal_Say(&a);
Animal* p = &a;             Animal* p = &a;
p->Say();                   (*(p->vptr[1]))(p);
函数调用
• 对象类型参数传递

• 对象类型参数返回

• 临时对象

• Return Value Optimization
简单类型函数调用
int sum(int a, int b) {
   int result = a + b;
   return result;
}

int main(int argc, char* argv[])
{
   sum(1, 4);
   return 0;
}




* 调用栈与机器架构有          , 这里以x86为例.
简单类型函数调用
                                   ...
int sum(int a, int b) {
   int result = a + b;              4
   return result;
}
                                    1
int main(int argc, char* argv[])
{
   sum(1, 4);
   return 0;
}




* 调用栈与机器架构有          , 这里以x86为例.
简单类型函数调用
                                        ...
int sum(int a, int b) {
   int result = a + b;                   4
   return result;
}
                                         1
int main(int argc, char* argv[])
{                                  Return Address
   sum(1, 4);
   return 0;
}




* 调用栈与机器架构有          , 这里以x86为例.
简单类型函数调用
                                              ...
int sum(int a, int b) {             5
   int result = a + b;             eax         4
   return result;
}
                                               1
int main(int argc, char* argv[])
{                                        Return Address
   sum(1, 4);
   return 0;
}                                  ebp     Saved ebp


                                   esp        sum


* 调用栈与机器架构有          , 这里以x86为例.
类类型参数传递
class Money {
 public:
   Money Add(Money money);

  private:
   uint64_t amount;
};

Money item(700);
Money freight(10);

Money total = item.Add(freight);
类类型参数传递
                                         ...
class Money {
 public:
   Money Add(Money money);         temp - Money(10)

  private:
   uint64_t amount;
};

Money item(700);
Money freight(10);

Money total = item.Add(freight);
类类型参数传递
                                         ...
class Money {
 public:
   Money Add(Money money);         temp - Money(10)

  private:
   uint64_t amount;
};                                 Return Address

Money item(700);
Money freight(10);

Money total = item.Add(freight);
类类型参数传递
                                               ...
class Money {
 public:
   Money Add(Money money);               temp - Money(10)

  private:
   uint64_t amount;
};                                       Return Address

Money item(700);
Money freight(10);                 ebp      Saved ebp

Money total = item.Add(freight);   esp         sum
类类型返回值
class Money {
 public:
   Money Add(Money money);

  private:
   uint64_t amount;
};

Money item(700);
Money freight(10);

Money total = item.Add(freight);
类类型返回值
class Money {                      void Money_Add(
 public:                               Money* this,
   Money Add(Money money);             Money* ret,
                                       Money money)
  private:                         {
   uint64_t amount;                    Money result = ...;
};                                     *ret = result;
                                   }
Money item(700);                   ...
Money freight(10);
                                   Money temp;
Money total = item.Add(freight);   Money_Add(&item, &temp, freight);
                                   Money total = temp;
                                   temp.Money::~Money();
类类型返回值
class Money {                      void Money_Add(
 public:                               Money* this,
   Money Add(Money money);             Money* ret,
                                       Money money)
  private:                         {
   uint64_t amount;                    Money result = ...;
};                                     *ret = result;
                                   }
Money item(700);                   ...
Money freight(10);
                                   Money temp;
Money total = item.Add(freight);   Money_Add(&item, &temp, freight);
                                   Money total = temp;
                                   temp.Money::~Money();
临时对象
• 函数调用的参数传递与返回

• 额外的对象构造与析构

• 额外的对象拷贝

• 可能戏剧性的影响程序效率
Tips 2


   Prefer pass-by-reference
      to pass-by-value
Return Value Optimization
void Money_Add(
  Money* this,
  Money* ret,
  Money money)
{
  Money result = ...;
  *ret = result;
}

Money item(700);
Money freight(10);

Money temp;
Money_Add(&item, &temp, freight);
Money total = temp;
Return Value Optimization
void Money_Add(                     void Money_Add(
  Money* this,                        Money* this,
  Money* ret,                         Money* ret,
  Money money)                        Money money)
{                                   {
  Money result = ...;                 *ret = ...;
  *ret = result;                    }
}
                                    Money item(700);
Money item(700);                    Money freight(10);
Money freight(10);
                                    Money temp;
Money temp;                         Money total;
Money_Add(&item, &temp, freight);   Money_Add(&item, &total, freight);
Money total = temp;
Return Value Optimization
void Money_Add(                     void Money_Add(
  Money* this,                        Money* this,
  Money* ret,                         Money* ret,
  Money money)                        Money money)
{                                   {
  Money result = ...;                 *ret = ...;
  *ret = result;                    }
}
                                    Money item(700);
Money item(700);                    Money freight(10);
Money freight(10);
                                    Money temp;
Money temp;                         Money total;
Money_Add(&item, &temp, freight);   Money_Add(&item, &total, freight);
Money total = temp;
std::string

• Implementations

  - Eager Copy

  - CoW - Copy on Write

  - SSO - Small String Optimization
Copy on Write
         string
   data : char*
Copy on Write

    string            "hello"
data : char*


                     5 30 1 h e   l   l   o ...
Copy on Write

    string              "hello"
data : char*
                        capacity


                      5 30 1 h e      l    l   o ...
                     size     引用计数   数据区
SSO
      string
data : char*
size : size_t
capacity : size_t
buffer : char[16]
Small String
      string                "hello"
data : char*
                          0x12345678
size : size_t
capacity : size_t
buffer : char[16]
                               5

                        h e l l o
Big String
"hell ..."        h e   l   l ...

0x12345678


   20



   32
Tips 3


  Critically Analyze What
   You Read And Hear
静态变量初始化

Animal animal("Lion");

int Foo() {
   ...
}

int num = Foo();
静态变量初始化

Animal animal("Lion");   void __sti_ii() {
                           animal.Animal::Animal();
int Foo() {                num = Foo();
   ...                   }
}
                         void __std_ii() {
int num = Foo();           animal.Animal::~Animal();
                         }
inline vs. iterator
vector<int>::iterator it = vec.begin();
vector<int>::iterator end = vec.end();    for (vector<int>::iterator it = vec.begin();
for (; it != end; ++it) {                      it != vec.end(); ++it) {


}                                         }
inline vs. iterator
vector<int>::iterator it = vec.begin();
vector<int>::iterator end = vec.end();    for (vector<int>::iterator it = vec.begin();
for (; it != end; ++it) {                      it != vec.end(); ++it) {

     it = vec.erase(it);                        it = vec.erase(it);
}                                         }
inline vs. iterator
vector<int>::iterator it = vec.begin();
vector<int>::iterator end = vec.end();    for (vector<int>::iterator it = vec.begin();
for (; it != end; ++it) {                      it != vec.end(); ++it) {

     it = vec.erase(it);                        it = vec.erase(it);
}                                         }
Tips 4


         Don't Assume It,
            Prove It
Prove I t!
• Only Code Never Lies

• Assembly Language

• g++

  - -S

• nm
References
• Bjarne Stroustrup. 1994. The Design And
  Evolution of C++

• Stanley B. Lippman. 1996. Inside the C++
  Object Model

• Scott Meyers. 2006. Effective C++

• 陈硕. 2012. C++工程实践
Q&A
Thanks for your time

Mysterious c++

  • 1.
    Mysterious c++ Traps, Pitfalls and Secrets Kent Wang Jun 1, 2012
  • 2.
    Why this talk •警惕靠巧合编程 • 勿在浮沙筑高台 • 了若指掌方可收放自如 • 见山非山, 见水非水
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
    sizeof class A { class B { class C { }; char c; virtual void foo(); }; char c; };
  • 13.
    sizeof class A { class B { class C { }; char c; virtual void foo(); }; char c; }; 1
  • 14.
    sizeof class A { class B { class C { }; char c; virtual void foo(); }; char c; }; 1 4
  • 15.
    sizeof class A { class B { class C { }; char c; virtual void foo(); }; char c; }; 1 4 8
  • 16.
    Constructor class Animal { public: Animal() { Animal("Lion", 21); Run(); } Animal(const string& name, int age); virtual void Run() = 0; };
  • 17.
    Constructor class Animal { public: Animal() { Animal("Lion", 21); Run(); } Animal(const string& name, int age); virtual void Run() = 0; };
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
    Function Object Member Function pointer Temporal Object dynamic_cast Function pointer Pass By Reference Pure Virtual Class RTTI typeid Overloading Pass By Value Pure Virtual Function Copy Constructor Virtual Function Multiple Inheritance Constructor Dynamic Binding Inheritance Exception Destructor Class Virtual Inheritance Friend Template String Adaptor Namespace STL Operator New RAII Iterator Function Template Class Template Template Specialization Memory Management Partial Specialization Smart Pointer Reference Preprocessor Template Meta Programming
  • 25.
    知乎? • 构造和析构函数机制是如何实现的? • 函数调用是如何传递及返回对象的? • 函数重载是如何实现的? • 多态是如何实现的? • 常机制是如何实现的?为何我们不用? • 静态变量是如何初始化的?
  • 26.
    Tips 1 Don't live with unknown unknowns
  • 27.
    What to talk •C++语言演化历史 • Object Memory Layout • 函数调用语义及临时对象 • 静态变量初始化
  • 28.
    What NOT totalk • 语法细节 • 二进制兼容性 • Exception Handling • Template & Generic Programming • C++11 (C++0x)
  • 29.
    Outline • 青梅煮酒论英雄 • 天机亦可泄露 - 对象内存模型 - 函数转换 - 函数调用 - 临时对象
  • 30.
  • 31.
    Timeline 2011 1980 1989 C++11 C with class CFront 2.0 1992 HP C++ Lambda Expression Class Multiple Inheritance Automatic Type Inheritance Abstract Class Exception Threading 1983 - 1986 1991 1996 C++ - CFront 1.1 CFront 3.0 C++ 98/03 Virtual Function Template STL Overloading Namespace Reference
  • 32.
  • 33.
  • 34.
    缘起 值语义 零负担 C兼容性 惯用法 编译器隐 藏操作
  • 35.
    C兼容性 • class Foo{}; - unnamed structure in C • Header File • Preprocessor / macros
  • 36.
    C兼容性 • class Foo{}; - unnamed structure in C struct { int a; int b • Header File } foo; foo.a = 10; • Preprocessor / macros
  • 37.
    零负担 • 不对栈变量自动初始化 • Objecton Stack • 默认构造函数不对POD类型进行初始化 • 成员函数默认为非虚函数
  • 38.
  • 39.
    值语义 Person kent("kent"); Person lazy= kent; kent "kent" lazy "kent"
  • 40.
  • 41.
  • 42.
    Not very goodat OO • No reflection and dynamic creation • Object lifetime management • Complex syntax stops refactoring tools
  • 44.
  • 46.
  • 47.
    C++ is deterministic •Destructing is determinate - No GC • Performance is predictable - C++ is fast only when coders are experts - Java is almost as fast, much higher productivity
  • 48.
    Where the FocusIs Efficiency Flexibility Abstraction Productivity C non-goal non-goal C++ non-goal at the at the Java, C# expense of expense of
  • 49.
    Conclusion • There areonly two kinds of languages - The ones people always complain about - The ones nobody uses • C++ is an undoubted success • One language doesn’t fit all - Important to known when and when not
  • 50.
  • 51.
  • 52.
    简单对象 class Animal { public: void Run(); private: char* name; int age; char sex; };
  • 53.
    简单对象 class Animal { name public: void Run(); private: age char* name; int age; char sex; }; Sex Alignment
  • 54.
    单一继承 class Animal { public: void Run(); private: char* name; int age; char sex; }; class Lion : public Animal { private: char* address; };
  • 55.
    单一继承 class Animal { address public: void Run(); private: name char* name; int age; char sex; }; age class Lion : public Animal { private: char* address; Sex Alignment };
  • 56.
    虚函数 class Animal { public: void Run(); virtual void Say(); private: char* name; int age; char sex; }; * vptr的偏移量与编译器实现有 .
  • 57.
    虚函数 class Animal { vptr public: void Run(); virtual void Say(); name private: char* name; age int age; char sex; }; Sex Alignment * vptr的偏移量与编译器实现有 .
  • 58.
    vptr and vtbl vptr name age Sex Alignment
  • 59.
    vptr and vtbl vptr 0 type_info type_info name 1 Say &Animal::Say age Sex Alignment vtbl$Animal
  • 60.
    带虚函数的继承 class Animal { public: virtual void Run(); virtual void Say(); private: char* name; int age; char sex; }; class Lion { public: virtual void Say(); };
  • 61.
    带虚函数的继承 class Animal { public: virtual void Run(); virtual void Say(); vptr private: name char* name; int age; char sex; age }; class Lion { Sex Alignment public: virtual void Say(); };
  • 62.
    vptr and vtbl vptr name age Sex Alignment
  • 63.
    vptr and vtbl vptr 0 type_info type_info name 1 Run &Animal::Run age 2 Say &Lion::Say Sex Alignment vtbl$Lion
  • 64.
    M o re • 多重继承 • 带虚函数的多重继承 •虚继承 • 带虚函数的虚继承 • 多重虚继承
  • 65.
    函数转换 class Animal{ public: void Run(); private: ... }; Animal a; a.Run(); * 真实情况下编译器会对函数名称进行编码,即name mangling.
  • 66.
    函数转换 class Animal{ public: void Run(); private: ... }; Animal a; a.Run(); * 真实情况下编译器会对函数名称进行编码,即name mangling.
  • 67.
    函数转换 class Animal{ void Animal_Run(Animal* this) public: { void Run(); ... } private: ... Animal a; }; Animal_Run(&a); Animal a; a.Run(); * 真实情况下编译器会对函数名称进行编码,即name mangling.
  • 68.
    函数转换 class Animal{ void Animal_Run(Animal* this) public: { void Run(); ... } private: ... Animal a; }; Animal_Run(&a); Animal a; a.Run(); * 真实情况下编译器会对函数名称进行编码,即name mangling.
  • 69.
    虚函数转换 class Animal { public: void Run(); virtual void Say(); private: ... }; Animal a; a.Say(); Animal* p = &a; p->Say();
  • 70.
    虚函数转换 class Animal { void Animal_ctor(Animal* this) public: { void Run(); this.vptr = &Animal_vtbl; virtual void Say(); } private: void Animal_Say(Animal* this) ... { }; } Animal a; Animal a; a.Say(); Animal_ctor(&a); Animal_Say(&a); Animal* p = &a; Animal* p = &a; p->Say(); (*(p->vptr[1]))(p);
  • 71.
    虚函数转换 class Animal { void Animal_ctor(Animal* this) public: { void Run(); this.vptr = &Animal_vtbl; virtual void Say(); } private: void Animal_Say(Animal* this) ... { }; } Animal a; Animal a; a.Say(); Animal_ctor(&a); Animal_Say(&a); Animal* p = &a; Animal* p = &a; p->Say(); (*(p->vptr[1]))(p);
  • 72.
  • 73.
    简单类型函数调用 int sum(int a,int b) { int result = a + b; return result; } int main(int argc, char* argv[]) { sum(1, 4); return 0; } * 调用栈与机器架构有 , 这里以x86为例.
  • 74.
    简单类型函数调用 ... int sum(int a, int b) { int result = a + b; 4 return result; } 1 int main(int argc, char* argv[]) { sum(1, 4); return 0; } * 调用栈与机器架构有 , 这里以x86为例.
  • 75.
    简单类型函数调用 ... int sum(int a, int b) { int result = a + b; 4 return result; } 1 int main(int argc, char* argv[]) { Return Address sum(1, 4); return 0; } * 调用栈与机器架构有 , 这里以x86为例.
  • 76.
    简单类型函数调用 ... int sum(int a, int b) { 5 int result = a + b; eax 4 return result; } 1 int main(int argc, char* argv[]) { Return Address sum(1, 4); return 0; } ebp Saved ebp esp sum * 调用栈与机器架构有 , 这里以x86为例.
  • 77.
    类类型参数传递 class Money { public: Money Add(Money money); private: uint64_t amount; }; Money item(700); Money freight(10); Money total = item.Add(freight);
  • 78.
    类类型参数传递 ... class Money { public: Money Add(Money money); temp - Money(10) private: uint64_t amount; }; Money item(700); Money freight(10); Money total = item.Add(freight);
  • 79.
    类类型参数传递 ... class Money { public: Money Add(Money money); temp - Money(10) private: uint64_t amount; }; Return Address Money item(700); Money freight(10); Money total = item.Add(freight);
  • 80.
    类类型参数传递 ... class Money { public: Money Add(Money money); temp - Money(10) private: uint64_t amount; }; Return Address Money item(700); Money freight(10); ebp Saved ebp Money total = item.Add(freight); esp sum
  • 81.
    类类型返回值 class Money { public: Money Add(Money money); private: uint64_t amount; }; Money item(700); Money freight(10); Money total = item.Add(freight);
  • 82.
    类类型返回值 class Money { void Money_Add( public: Money* this, Money Add(Money money); Money* ret, Money money) private: { uint64_t amount; Money result = ...; }; *ret = result; } Money item(700); ... Money freight(10); Money temp; Money total = item.Add(freight); Money_Add(&item, &temp, freight); Money total = temp; temp.Money::~Money();
  • 83.
    类类型返回值 class Money { void Money_Add( public: Money* this, Money Add(Money money); Money* ret, Money money) private: { uint64_t amount; Money result = ...; }; *ret = result; } Money item(700); ... Money freight(10); Money temp; Money total = item.Add(freight); Money_Add(&item, &temp, freight); Money total = temp; temp.Money::~Money();
  • 84.
    临时对象 • 函数调用的参数传递与返回 • 额外的对象构造与析构 •额外的对象拷贝 • 可能戏剧性的影响程序效率
  • 85.
    Tips 2 Prefer pass-by-reference to pass-by-value
  • 86.
    Return Value Optimization voidMoney_Add( Money* this, Money* ret, Money money) { Money result = ...; *ret = result; } Money item(700); Money freight(10); Money temp; Money_Add(&item, &temp, freight); Money total = temp;
  • 87.
    Return Value Optimization voidMoney_Add( void Money_Add( Money* this, Money* this, Money* ret, Money* ret, Money money) Money money) { { Money result = ...; *ret = ...; *ret = result; } } Money item(700); Money item(700); Money freight(10); Money freight(10); Money temp; Money temp; Money total; Money_Add(&item, &temp, freight); Money_Add(&item, &total, freight); Money total = temp;
  • 88.
    Return Value Optimization voidMoney_Add( void Money_Add( Money* this, Money* this, Money* ret, Money* ret, Money money) Money money) { { Money result = ...; *ret = ...; *ret = result; } } Money item(700); Money item(700); Money freight(10); Money freight(10); Money temp; Money temp; Money total; Money_Add(&item, &temp, freight); Money_Add(&item, &total, freight); Money total = temp;
  • 89.
    std::string • Implementations - Eager Copy - CoW - Copy on Write - SSO - Small String Optimization
  • 90.
    Copy on Write string data : char*
  • 91.
    Copy on Write string "hello" data : char* 5 30 1 h e l l o ...
  • 92.
    Copy on Write string "hello" data : char* capacity 5 30 1 h e l l o ... size 引用计数 数据区
  • 93.
    SSO string data : char* size : size_t capacity : size_t buffer : char[16]
  • 94.
    Small String string "hello" data : char* 0x12345678 size : size_t capacity : size_t buffer : char[16] 5 h e l l o
  • 95.
    Big String "hell ..." h e l l ... 0x12345678 20 32
  • 96.
    Tips 3 Critically Analyze What You Read And Hear
  • 97.
  • 98.
    静态变量初始化 Animal animal("Lion"); void __sti_ii() { animal.Animal::Animal(); int Foo() { num = Foo(); ... } } void __std_ii() { int num = Foo(); animal.Animal::~Animal(); }
  • 99.
    inline vs. iterator vector<int>::iteratorit = vec.begin(); vector<int>::iterator end = vec.end(); for (vector<int>::iterator it = vec.begin(); for (; it != end; ++it) { it != vec.end(); ++it) { } }
  • 100.
    inline vs. iterator vector<int>::iteratorit = vec.begin(); vector<int>::iterator end = vec.end(); for (vector<int>::iterator it = vec.begin(); for (; it != end; ++it) { it != vec.end(); ++it) { it = vec.erase(it); it = vec.erase(it); } }
  • 101.
    inline vs. iterator vector<int>::iteratorit = vec.begin(); vector<int>::iterator end = vec.end(); for (vector<int>::iterator it = vec.begin(); for (; it != end; ++it) { it != vec.end(); ++it) { it = vec.erase(it); it = vec.erase(it); } }
  • 102.
    Tips 4 Don't Assume It, Prove It
  • 103.
    Prove I t! • OnlyCode Never Lies • Assembly Language • g++ - -S • nm
  • 104.
    References • Bjarne Stroustrup.1994. The Design And Evolution of C++ • Stanley B. Lippman. 1996. Inside the C++ Object Model • Scott Meyers. 2006. Effective C++ • 陈硕. 2012. C++工程实践
  • 105.
  • 106.