五万字读懂c++

const作用

  1. 修饰变量,说明该变量不可以被改变;
  2. 修饰指针,分为指向常量的指针(pointer to const)和自身是常量的指针(常量指针,const pointer);
  3. 修饰引用,指向常量的引用(reference to const),用于形参类型,即避免了拷贝,又避免了函数对值的修改;
  4. 修饰成员函数,说明该成员函数内不能修改成员变量。

const 的指针与引用

  • 指针
    • 指向常量的指针(pointer to const)
    • 自身是常量的指针(常量指针,const pointer)
  • 引用
    • 指向常量的引用(reference to const)
    • 没有 const reference,因为引用只是对象的别名,引用不是对象,不能用 const 修饰

(为了方便记忆可以想成)被 const 修饰(在 const 后面)的值不可改变,如下文使用例子中的 p2p3

使用

const 使用

// 类class A{private:    const int a;                // 常对象成员,可以使用初始化列表或者类内初始化public:    // 构造函数    A() : a(0) { };    A(int x) : a(x) { };        // 初始化列表    // const可用于对重载函数的区分    int getValue();             // 普通成员函数    int getValue() const;       // 常成员函数,不得修改类中的任何数据成员的值};void function(){    // 对象    A b;                        // 普通对象,可以调用全部成员函数    const A a;                  // 常对象,只能调用常成员函数    const A *p = &a;            // 指针变量,指向常对象    const A &q = a;             // 指向常对象的引用    // 指针    char greeting[] = "Hello";    char* p1 = greeting;                // 指针变量,指向字符数组变量    const char* p2 = greeting;          // 指针变量,指向字符数组常量(const 后面是 char,说明指向的字符(char)不可改变)    char* const p3 = greeting;          // 自身是常量的指针,指向字符数组变量(const 后面是 p3,说明 p3 指针自身不可改变)    const char* const p4 = greeting;    // 自身是常量的指针,指向字符数组常量}// 函数void function1(const int Var);           // 传递过来的参数在函数内不可变void function2(const char* Var);         // 参数指针所指内容为常量void function3(char* const Var);         // 参数指针为常量void function4(const int& Var);          // 引用参数在函数内为常量// 函数返回值const int function5();      // 返回一个常数const int* function6();     // 返回一个指向常量的指针变量,使用:const int *p = function6();int* const function7();     // 返回一个指向变量的常指针,使用:int* const p = function7();

宏定义 #define 和 const 常量

宏定义 #defineconst 常量
宏定义,相当于字符替换常量声明
预处理器处理编译器处理
无类型安全检查有类型安全检查
不分配内存要分配内存
存储在代码段存储在数据段
可通过 #undef 取消不可取消

static

作用

  1. 修饰普通变量,修改变量的存储区域和生命周期,使变量存储在静态区,在 main 函数运行前就分配了空间,如果有初始值就用初始值初始化它,如果没有初始值系统用默认值初始化它。
  2. 修饰普通函数,表明函数的作用范围,仅在定义该函数的文件内才能使用。在多人开发项目时,为了防止与他人命名空间里的函数重名,可以将函数定位为 static。
  3. 修饰成员变量,修饰成员变量使所有的对象只保存一个该变量,而且不需要生成对象就可以访问该成员。
  4. 修饰成员函数,修饰成员函数使得不需要生成对象就可以访问该函数,但是在 static 函数内不能访问非静态成员。

this 指针

  1. this 指针是一个隐含于每一个非静态成员函数中的特殊指针。它指向调用该成员函数的那个对象。
  2. 当对一个对象调用成员函数时,编译程序先将对象的地址赋给 this 指针,然后调用成员函数,每次成员函数存取数据成员时,都隐式使用 this 指针。
  3. 当一个成员函数被调用时,自动向它传递一个隐含的参数,该参数是一个指向这个成员函数所在的对象的指针。
  4. this 指针被隐含地声明为: ClassName *const this,这意味着不能给 this 指针赋值;在 ClassName 类的 const 成员函数中,this 指针的类型为:const ClassName* const,这说明不能对 this 指针所指向的这种对象是不可修改的(即不能对这种对象的数据成员进行赋值操作);
  5. this 并不是一个常规变量,而是个右值,所以不能取得 this 的地址(不能 &this)。
  6. 在以下场景中,经常需要显式引用this
    指针:
    1. 为实现对象的链式引用;
    2. 为避免对同一对象进行赋值操作;
    3. 在实现一些数据结构时,如 list

inline 内联函数

特征

  • 相当于把内联函数里面的内容写在调用内联函数处;
  • 相当于不用执行进入函数的步骤,直接执行函数体;
  • 相当于宏,却比宏多了类型检查,真正具有函数特性;
  • 编译器一般不内联包含循环、递归、switch 等复杂操作的内联函数;
  • 在类声明中定义的函数,除了虚函数的其他函数都会自动隐式地当成内联函数。

使用

inline 使用

// 声明1(加 inline,建议使用)inline int functionName(int first, int second,...);// 声明2(不加 inline)int functionName(int first, int second,...);// 定义inline int functionName(int first, int second,...) {/****/};// 类内定义,隐式内联class A {    int doA() { return 0; }         // 隐式内联}// 类外定义,需要显式内联class A {    int doA();}inline int A::doA() { return 0; }   // 需要显式内联

编译器对 inline 函数的处理步骤

  1. 将 inline 函数体复制到 inline 函数调用点处;
  2. 为所用 inline 函数中的局部变量分配内存空间;
  3. 将 inline 函数的的输入参数和返回值映射到调用方法的局部变量空间中;
  4. 如果 inline 函数有多个返回点,将其转变为 inline 函数代码块末尾的分支(使用 GOTO)。

优缺点

优点

  1. 内联函数同宏函数一样将在被调用处进行代码展开,省去了参数压栈、栈帧开辟与回收,结果返回等,从而提高程序运行速度。
  2. 内联函数相比宏函数来说,在代码展开时,会做安全检查或自动类型转换(同普通函数),而宏定义则不会。
  3. 在类中声明同时定义的成员函数,自动转化为内联函数,因此内联函数可以访问类的成员变量,宏定义则不能。
  4. 内联函数在运行时可调试,而宏定义不可以。

缺点

  1. 代码膨胀。内联是以代码膨胀(复制)为代价,消除函数调用带来的开销。如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
  2. inline 函数无法随着函数库升级而升级。inline函数的改变需要重新编译,不像 non-inline 可以直接链接。
  3. 是否内联,程序员不可控。内联函数只是对编译器的建议,是否对函数内联,决定权在于编译器。

虚函数(virtual)可以是内联函数(inline)吗?

Are “inline virtual” member functions ever actually “inlined”?

  • 虚函数可以是内联函数,内联是可以修饰虚函数的,但是当虚函数表现多态性的时候不能内联。
  • 内联是在编译器建议编译器内联,而虚函数的多态性在运行期,编译器无法知道运行期调用哪个代码,因此虚函数表现为多态性时(运行期)不可以内联。
  • inline virtual 唯一可以内联的时候是:编译器知道所调用的对象是哪个类(如 Base::who()),这只有在编译器具有实际对象而不是对象的指针或引用时才会发生。

虚函数内联使用

#include <iostream>  using namespace std;class Base{public: inline virtual void who() {  cout << "I am Base\n"; } virtual ~Base() {}};class Derived : public Base{public: inline void who()  // 不写inline时隐式内联 {  cout << "I am Derived\n"; }};int main(){ // 此处的虚函数 who(),是通过类(Base)的具体对象(b)来调用的,编译期间就能确定了,所以它可以是内联的,但最终是否内联取决于编译器。  Base b; b.who(); // 此处的虚函数是通过指针调用的,呈现多态性,需要在运行时期间才能确定,所以不能为内联。   Base *ptr = new Derived(); ptr->who(); // 因为Base有虚析构函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derived)析构函数,再调用基类(Base)析构函数,防止内存泄漏。 delete ptr; ptr = nullptr; system("pause"); return 0;} 

volatile

volatile int i = 10; 
  • volatile 关键字是一种类型修饰符,用它声明的类型变量表示可以被某些编译器未知的因素(操作系统、硬件、其它线程等)更改。所以使用 volatile 告诉编译器不应对这样的对象进行优化。
  • volatile 关键字声明的变量,每次访问时都必须从内存中取出值(没有被 volatile 修饰的变量,可能由于编译器的优化,从 CPU 寄存器中取值)
  • const 可以是 volatile (如只读的状态寄存器)
  • 指针可以是 volatile

assert()

断言,是宏,而非函数。assert 宏的原型定义在 <assert.h>(C)、<cassert>(C++)中,其作用是如果它的条件返回错误,则终止程序执行。可以通过定义 NDEBUG 来关闭 assert,但是需要在源代码的开头,include <assert.h> 之前。

assert() 使用

#define NDEBUG          // 加上这行,则 assert 不可用#include <assert.h>assert( p != NULL );    // assert 不可用

sizeof()

  • sizeof 对数组,得到整个数组所占空间大小。
  • sizeof 对指针,得到指针本身所占空间大小。

#pragma pack(n)

设定结构体、联合以及类成员变量以 n 字节方式对齐

#pragma pack(n) 使用

#pragma pack(push)  // 保存对齐状态#pragma pack(4)     // 设定为 4 字节对齐struct test{    char m1;    double m4;    int m3;};#pragma pack(pop)   // 恢复对齐状态

位域

Bit mode: 2;    // mode 占 2 位

类可以将其(非静态)数据成员定义为位域(bit-field),在一个位域中含有一定数量的二进制位。当一个程序需要向其他程序或硬件设备传递二进制数据时,通常会用到位域。

  • 位域在内存中的布局是与机器有关的
  • 位域的类型必须是整型或枚举类型,带符号类型中的位域的行为将因具体实现而定
  • 取地址运算符(&)不能作用于位域,任何指针都无法指向类的位域

extern “C”

  • 被 extern 限定的函数或变量是 extern 类型的
  • 被 extern "C" 修饰的变量和函数是按照 C 语言方式编译和链接的

extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代码当作 C 语言代码处理,可以避免 C++ 因符号修饰导致代码不能和C语言库中的符号进行链接的问题。

extern “C” 使用

#ifdef __cplusplusextern "C" {#endifvoid *memset(void *, int, size_t);#ifdef __cplusplus}#endif

struct 和 typedef struct

C 中

// ctypedef struct Student {    int age; } S;

等价于

// cstruct Student {     int age; };typedef struct Student S;

此时 S 等价于 struct Student,但两个标识符名称空间不相同。

另外还可以定义与 struct Student 不冲突的 void Student() {}

C++ 中

由于编译器定位符号的规则(搜索规则)改变,导致不同于C语言。

一、如果在类标识符空间定义了 struct Student {...};,使用 Student me; 时,编译器将搜索全局标识符表,Student 未找到,则在类标识符内搜索。

即表现为可以使用 Student 也可以使用 struct Student,如下:

// cppstruct Student {     int age; };void f( Student me );       // 正确,"struct" 关键字可省略

二、若定义了与 Student 同名函数之后,则 Student 只代表函数,不代表结构体,如下:

typedef struct Student {     int age; } S;void Student() {}           // 正确,定义后 "Student" 只代表此函数//void S() {}               // 错误,符号 "S" 已经被定义为一个 "struct Student" 的别名int main() {    Student();     struct Student me;      // 或者 "S me";    return 0;}

C++ 中 struct 和 class

总的来说,struct 更适合看成是一个数据结构的实现体,class 更适合看成是一个对象的实现体。

区别

  • 最本质的一个区别就是默认的访问控制
    1. 默认的继承访问权限。struct 是 public 的,class 是 private 的。
    2. struct 作为数据结构的实现体,它默认的数据访问控制是 public 的,而 class 作为对象的实现体,它默认的成员变量访问控制是 private 的。

union 联合

联合(union)是一种节省空间的特殊的类,一个 union 可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。当某个成员被赋值后其他成员变为未定义状态。联合有如下特点:

  • 默认访问控制符为 public
  • 可以含有构造函数、析构函数
  • 不能含有引用类型的成员
  • 不能继承自其他类,不能作为基类
  • 不能含有虚函数
  • 匿名 union 在定义所在作用域可直接访问 union 成员
  • 匿名 union 不能包含 protected 成员或 private 成员
  • 全局匿名联合必须是静态(static)的

union 使用

#include<iostream>union UnionTest {    UnionTest() : i(10) {};    int i;    double d;};static union {    int i;    double d;};int main() {    UnionTest u;    union {        int i;        double d;    };    std::cout << u.i << std::endl;  // 输出 UnionTest 联合的 10    ::i = 20;    std::cout << ::i << std::endl;  // 输出全局静态匿名联合的 20    i = 30;    std::cout << i << std::endl;    // 输出局部匿名联合的 30    return 0;}

C 实现 C++ 类

C 实现 C++ 的面向对象特性(封装、继承、多态)

  • 封装:使用函数指针把属性与方法封装到结构体中
  • 继承:结构体嵌套
  • 多态:父类与子类方法的函数指针不同

[Can you write object-oriented code in C? closed]

explicit(显式)关键字

  • explicit 修饰构造函数时,可以防止隐式转换和复制初始化
  • explicit 修饰转换函数时,可以防止隐式转换,但 按语境转换 除外

explicit 使用

struct A{ A(int) { } operator bool() const { return true; }};struct B{ explicit B(int) {} explicit operator bool() const { return true; }};void doA(A a) {}void doB(B b) {}int main(){ A a1(1);  // OK:直接初始化 A a2 = 1;  // OK:复制初始化 A a3{ 1 };  // OK:直接列表初始化 A a4 = { 1 };  // OK:复制列表初始化 A a5 = (A)1;  // OK:允许 static_cast 的显式转换  doA(1);   // OK:允许从 int 到 A 的隐式转换 if (a1);  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a6(a1);  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a7 = a1;  // OK:使用转换函数 A::operator bool() 的从 A 到 bool 的隐式转换 bool a8 = static_cast<bool>(a1);  // OK :static_cast 进行直接初始化 B b1(1);  // OK:直接初始化 B b2 = 1;  // 错误:被 explicit 修饰构造函数的对象不可以复制初始化 B b3{ 1 };  // OK:直接列表初始化 B b4 = { 1 };  // 错误:被 explicit 修饰构造函数的对象不可以复制列表初始化 B b5 = (B)1;  // OK:允许 static_cast 的显式转换 doB(1);   // 错误:被 explicit 修饰构造函数的对象不可以从 int 到 B 的隐式转换 if (b1);  // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b6(b1);  // OK:被 explicit 修饰转换函数 B::operator bool() 的对象可以从 B 到 bool 的按语境转换 bool b7 = b1;  // 错误:被 explicit 修饰转换函数 B::operator bool() 的对象不可以隐式转换 bool b8 = static_cast<bool>(b1);  // OK:static_cast 进行直接初始化 return 0;}

friend 友元类和友元函数

  • 能访问私有成员
  • 破坏封装性
  • 友元关系不可传递
  • 友元关系的单向性
  • 友元声明的形式及数量不受限制

using

using 声明

一条 using 声明 语句一次只引入命名空间的一个成员。它使得我们可以清楚知道程序中所引用的到底是哪个名字。如:

using namespace_name::name;

构造函数的 using 声明

在 C++11 中,派生类能够重用其直接基类定义的构造函数。

class Derived : Base {public:    using Base::Base;    /* ... */};

如上 using 声明,对于基类的每个构造函数,编译器都生成一个与之对应(形参列表完全相同)的派生类构造函数。生成如下类型构造函数:

Derived(parms) : Base(args) { }

using 指示

using 指示 使得某个特定命名空间中所有名字都可见,这样我们就无需再为它们添加任何前缀限定符了。如:

using namespace_name name;

尽量少使用 using 指示 污染命名空间

一般说来,使用 using 命令比使用 using 编译命令更安全,这是由于它只导入了指定的名称。如果该名称与局部名称发生冲突,编译器将发出指示。using编译命令导入所有的名称,包括可能并不需要的名称。如果与局部名称发生冲突,则局部名称将覆盖名称空间版本,而编译器并不会发出警告。另外,名称空间的开放性意味着名称空间的名称可能分散在多个地方,这使得难以准确知道添加了哪些名称。

using 使用

尽量少使用 using 指示

using namespace std;

应该多使用 using 声明

int x;std::cin >> x ;std::cout << x << std::endl;

或者

using std::cin;using std::cout;using std::endl;int x;cin >> x;cout << x << endl;

:: 范围解析运算符

分类

  1. 全局作用域符(::name):用于类型名称(类、类成员、成员函数、变量等)前,表示作用域为全局命名空间
  2. 类作用域符(class::name):用于表示指定类型的作用域范围是具体某个类的
  3. 命名空间作用域符(namespace::name):用于表示指定类型的作用域范围是具体某个命名空间的

:: 使用

int count = 11;         // 全局(::)的 countclass A {public: static int count;   // 类 A 的 count(A::count)};int A::count = 21;void fun(){ int count = 31;     // 初始化局部的 count 为 31 count = 32;         // 设置局部的 count 的值为 32}int main() { ::count = 12;       // 测试 1:设置全局的 count 的值为 12 A::count = 22;      // 测试 2:设置类 A 的 count 为 22 fun();          // 测试 3 return 0;}

enum 枚举类型

限定作用域的枚举类型

enum class open_modes { input, output, append };

不限定作用域的枚举类型

enum color { red, yellow, green };enum { floatPrec = 6, doublePrec = 10 };

decltype

decltype 关键字用于检查实体的声明类型或表达式的类型及值分类。语法:

decltype ( expression )

decltype 使用

// 尾置返回允许我们在参数列表之后声明返回类型template <typename It>auto fcn(It beg, It end) -> decltype(*beg){    // 处理序列    return *beg;    // 返回序列中一个元素的引用}// 为了使用模板参数成员,必须用 typenametemplate <typename It>auto fcn2(It beg, It end) -> typename remove_reference<decltype(*beg)>::type{    // 处理序列    return *beg;    // 返回序列中一个元素的拷贝}

引用

左值引用

常规引用,一般表示对象的身份。

右值引用

右值引用就是必须绑定到右值(一个临时对象、将要销毁的对象)的引用,一般表示对象的值。

右值引用可实现转移语义(Move Sementics)和精确传递(Perfect Forwarding),它的主要目的有两个方面:

  • 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
  • 能够更简洁明确地定义泛型函数。

引用折叠

  • X& &X& &&X&& & 可折叠成 X&
  • X&& && 可折叠成 X&&

  • 宏定义可以实现类似于函数的功能,但是它终归不是函数,而宏定义中括弧中的“参数”也不是真的参数,在宏展开的时候对 “参数” 进行的是一对一的替换。

成员初始化列表

好处

  • 更高效:少了一次调用默认构造函数的过程。
  • 有些场合必须要用初始化列表:
    1. 常量成员,因为常量只能初始化不能赋值,所以必须放在初始化列表里面
    2. 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表里面
    3. 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化

initializer_list 列表初始化

用花括号初始化器列表初始化一个对象,其中对应构造函数接受一个 std::initializer_list 参数.

initializer_list 使用

#include <iostream>#include <vector>#include <initializer_list> template <class T>struct S {    std::vector<T> v;    S(std::initializer_list<T> l) : v(l) {         std::cout << "constructed with a " << l.size() << "-element list\n";    }    void append(std::initializer_list<T> l) {        v.insert(v.end(), l.begin(), l.end());    }    std::pair<const T*, std::size_t> c_arr() const {        return {&v[0], v.size()};  // 在 return 语句中复制列表初始化                                   // 这不使用 std::initializer_list    }}; template <typename T>void templated_fn(T) {} int main(){    S<int> s = {1, 2, 3, 4, 5}; // 复制初始化    s.append({6, 7, 8});      // 函数调用中的列表初始化     std::cout << "The vector size is now " << s.c_arr().second << " ints:\n";     for (auto n : s.v)        std::cout << n << ' ';    std::cout << '\n';     std::cout << "Range-for over brace-init-list: \n";     for (int x : {-1, -2, -3}) // auto 的规则令此带范围 for 工作        std::cout << x << ' ';    std::cout << '\n';     auto al = {10, 11, 12};   // auto 的特殊规则     std::cout << "The list bound to auto has size() = " << al.size() << '\n'; //    templated_fn({1, 2, 3}); // 编译错误!“ {1, 2, 3} ”不是表达式,                             // 它无类型,故 T 无法推导    templated_fn<std::initializer_list<int>>({1, 2, 3}); // OK    templated_fn<std::vector<int>>({1, 2, 3});           // 也 OK}

面向对象

面向对象程序设计(Object-oriented programming,OOP)是种具有对象概念的程序编程典范,同时也是一种程序开发的抽象方针。

面向对象三大特征 —— 封装、继承、多态

封装

把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。关键字:public, protected, private。不写默认为 private。

  • public 成员:可以被任意实体访问
  • protected 成员:只允许被子类及本类的成员函数访问
  • private 成员:只允许被本类的成员函数、友元类或友元函数访问

继承

  • 基类(父类)——> 派生类(子类)

多态

  • 多态,即多种状态(形态)。简单来说,我们可以将多态定义为消息以多种形式显示的能力。
  • 多态是以封装和继承为基础的。
  • C++ 多态分类及实现:
    1. 重载多态(Ad-hoc Polymorphism,编译期):函数重载、运算符重载
    2. 子类型多态(Subtype Polymorphism,运行期):虚函数
    3. 参数多态性(Parametric Polymorphism,编译期):类模板、函数模板
    4. 强制多态(Coercion Polymorphism,编译期/运行期):基本类型转换、自定义类型转换

The Four Polymorphisms in C++

静态多态(编译期/早绑定)

函数重载

class A{public:    void do(int a);    void do(int a, int b);};

动态多态(运行期期/晚绑定)

  • 虚函数:用 virtual 修饰成员函数,使其成为虚函数
  • 动态绑定:当使用基类的引用或指针调用一个虚函数时将发生动态绑定

注意:

  • 可以将派生类的对象赋值给基类的指针或引用,反之不可
  • 普通函数(非类成员函数)不能是虚函数
  • 静态函数(static)不能是虚函数
  • 构造函数不能是虚函数(因为在调用构造函数时,虚表指针并没有在对象的内存空间中,必须要构造函数调用完成后才会形成虚表指针)
  • 内联函数不能是表现多态性时的虚函数,解释见:虚函数(virtual)可以是内联函数(inline)吗?

动态多态使用

class Shape                     // 形状类{public:    virtual double calcArea()    {        ...    }    virtual ~Shape();};class Circle : public Shape     // 圆形类{public:    virtual double calcArea();    ...};class Rect : public Shape       // 矩形类{public:    virtual double calcArea();    ...};int main(){    Shape * shape1 = new Circle(4.0);    Shape * shape2 = new Rect(5.0, 6.0);    shape1->calcArea();         // 调用圆形类里面的方法    shape2->calcArea();         // 调用矩形类里面的方法    delete shape1;    shape1 = nullptr;    delete shape2;    shape2 = nullptr;    return 0;}

虚析构函数

虚析构函数是为了解决基类的指针指向派生类对象,并用基类的指针删除派生类对象。

虚析构函数使用

class Shape{public:    Shape();                    // 构造函数不能是虚函数    virtual double calcArea();    virtual ~Shape();           // 虚析构函数};class Circle : public Shape     // 圆形类{public:    virtual double calcArea();    ...};int main(){    Shape * shape1 = new Circle(4.0);    shape1->calcArea();        delete shape1;  // 因为Shape有虚析构函数,所以delete释放内存时,先调用子类析构函数,再调用基类析构函数,防止内存泄漏。    shape1 = NULL;    return 0;}

纯虚函数

纯虚函数是一种特殊的虚函数,在基类中不能对虚函数给出有意义的实现,而把它声明为纯虚函数,它的实现留给该基类的派生类去做。

virtual int A() = 0;

虚函数、纯虚函数

  • 类里如果声明了虚函数,这个函数是实现的,哪怕是空实现,它的作用就是为了能让这个函数在它的子类里面可以被覆盖(override),这样的话,编译器就可以使用后期绑定来达到多态了。纯虚函数只是一个接口,是个函数的声明而已,它要留到子类里去实现。
  • 虚函数在子类里面可以不重写;但纯虚函数必须在子类实现才可以实例化子类。
  • 虚函数的类用于 “实作继承”,继承接口的同时也继承了父类的实现。纯虚函数关注的是接口的统一性,实现由子类完成。
  • 带纯虚函数的类叫抽象类,这种类不能直接生成对象,而只有被继承,并重写其虚函数后,才能使用。抽象类被继承后,子类可以继续是抽象类,也可以是普通类。
  • 虚基类是虚继承中的基类,具体见下文虚继承。

CSDN . C++ 中的虚函数、纯虚函数区别和联系

虚函数指针、虚函数表

  • 虚函数指针:在含有虚函数类的对象中,指向虚函数表,在运行时确定。
  • 虚函数表:在程序只读数据段(.rodata section,见:目标文件存储结构),存放虚函数指针,如果派生类实现了基类的某个虚函数,则在虚表中覆盖原本基类的那个虚函数指针,在编译时根据类的声明创建。

C++中的虚函数(表)实现机制以及用C语言对其进行的模拟实现

虚继承

虚继承用于解决多继承条件下的菱形继承问题(浪费存储空间、存在二义性)。

底层实现原理与编译器相关,一般通过虚基类指针和虚基类表实现,每个虚继承的子类都有一个虚基类指针(占用一个指针的存储空间,4字节)和虚基类表(不占用类对象的存储空间)(需要强调的是,虚基类依旧会在子类里面存在拷贝,只是仅仅最多存在一份而已,并不是不在子类里面了);当虚继承的子类被当做父类继承时,虚基类指针也会被继承。

实际上,vbptr 指的是虚基类表指针(virtual base table pointer),该指针指向了一个虚基类表(virtual table),虚表中记录了虚基类与本类的偏移地址;通过偏移地址,这样就找到了虚基类成员,而虚继承也不用像普通多继承那样维持着公共基类(虚基类)的两份同样的拷贝,节省了存储空间。

虚继承、虚函数

  • 相同之处:都利用了虚指针(均占用类的存储空间)和虚表(均不占用类的存储空间)
  • 不同之处:
    • 虚函数不占用存储空间
    • 虚函数表存储的是虚函数地址
    • 虚基类依旧存在继承类中,只占用存储空间
    • 虚基类表存储的是虚基类相对直接继承类的偏移
    • 虚继承
    • 虚函数

模板类、成员模板、虚函数

  • 模板类中可以使用虚函数
  • 一个类(无论是普通类还是类模板)的成员模板(本身是模板的成员函数)不能是虚函数

抽象类、接口类、聚合类

  • 抽象类:含有纯虚函数的类
  • 接口类:仅含有纯虚函数的抽象类
  • 聚合类:用户可以直接访问其成员,并且具有特殊的初始化语法形式。满足如下特点:
    • 所有成员都是 public
    • 没有定义任何构造函数
    • 没有类内初始化
    • 没有基类,也没有 virtual 函数

内存分配和管理

malloc、calloc、realloc、alloca

  1. malloc:申请指定字节数的内存。申请到的内存中的初始值不确定。
  2. calloc:为指定长度的对象,分配能容纳其指定个数的内存。申请到的内存的每一位(bit)都初始化为 0。
  3. realloc:更改以前分配的内存长度(增加或减少)。当增加长度时,可能需将以前分配区的内容移到另一个足够大的区域,而新增区域内的初始值则不确定。
  4. alloca:在栈上申请内存。程序在出栈的时候,会自动释放内存。但是需要注意的是,alloca 不具可移植性, 而且在没有传统堆栈的机器上很难实现。alloca 不宜使用在必须广泛移植的程序中。C99 中支持变长数组 (VLA),可以用来替代 alloca。

malloc、free

用于分配、释放内存

malloc、free 使用

申请内存,确认是否申请成功

char *str = (char*) malloc(100);assert(str != nullptr);

释放内存后指针置空

free(p); p = nullptr;

new、delete

  1. new / new[]:完成两件事,先底层调用 malloc 分配了内存,然后调用构造函数(创建对象)。
  2. delete/delete[]:也完成两件事,先调用析构函数(清理资源),然后底层调用 free 释放空间。
  3. new 在申请内存时会自动计算所需字节数,而 malloc 则需我们自己输入申请内存空间的字节数。

new、delete 使用

申请内存,确认是否申请成功

int main(){    T* t = new T();     // 先内存分配 ,再构造函数    delete t;           // 先析构函数,再内存释放    return 0;}

定位 new

定位 new(placement new)允许我们向 new 传递额外的地址参数,从而在预先指定的内存区域创建对象。

new (place_address) typenew (place_address) type (initializers)new (place_address) type [size]new (place_address) type [size] { braced initializer list }
  • place_address 是个指针
  • initializers 提供一个(可能为空的)以逗号分隔的初始值列表

delete this 合法吗?

Is it legal (and moral) for a member function to say delete this?

合法,但:

  1. 必须保证 this 对象是通过 new(不是 new[]、不是 placement new、不是栈上、不是全局、不是其他对象成员)分配的
  2. 必须保证调用 delete this 的成员函数是最后一个调用 this 的成员函数
  3. 必须保证成员函数的 delete this后面没有调用 this 了
  4. 必须保证 delete this 后没有人使用了

如何定义一个只能在堆上(栈上)生成对象的类?

如何定义一个只能在堆上(栈上)生成对象的类?

只能在堆上

方法:将析构函数设置为私有

原因:C++ 是静态绑定语言,编译器管理栈上对象的生命周期,编译器在为类对象分配栈空间时,会先检查类的析构函数的访问性。若析构函数不可访问,则不能在栈上创建对象。

只能在栈上

方法:将 new 和 delete 重载为私有

原因:在堆上生成对象,使用 new 关键词操作,其过程分为两阶段:第一阶段,使用 new 在堆上寻找可用内存,分配给对象;第二阶段,调用构造函数生成对象。将 new 操作设置为私有,那么第一阶段就无法完成,就不能够在堆上生成对象。

智能指针

C++ 标准库(STL)中

头文件:#include <memory>

C++ 98

std::auto_ptr<std::string> ps (new std::string(str));

C++ 11

  1. shared_ptr
  2. unique_ptr
  3. weak_ptr
  4. auto_ptr(被 C++11 弃用)
  • Class shared_ptr 实现共享式拥有(shared ownership)概念。多个智能指针指向相同对象,该对象和其相关资源会在 “最后一个 reference 被销毁” 时被释放。为了在结构较复杂的情景中执行上述工作,标准库提供 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等辅助类。
  • Class unique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。你可以移交拥有权。它对于避免内存泄漏(resource leak)——如 new 后忘记 delete ——特别有用。
shared_ptr

多个智能指针可以共享同一个对象,对象的最末一个拥有着有责任销毁对象,并清理与该对象相关的所有资源。

  • 支持定制型删除器(custom deleter),可防范 Cross-DLL 问题(对象在动态链接库(DLL)中被 new 创建,却在另一个 DLL 内被 delete 销毁)、自动解除互斥锁
weak_ptr

weak_ptr 允许你共享但不拥有某对象,一旦最末一个拥有该对象的智能指针失去了所有权,任何 weak_ptr 都会自动成空(empty)。因此,在 default 和 copy 构造函数之外,weak_ptr 只提供 “接受一个 shared_ptr” 的构造函数。

  • 可打破环状引用(cycles of references,两个其实已经没有被使用的对象彼此互指,使之看似还在 “被使用” 的状态)的问题
unique_ptr

unique_ptr 是 C++11 才开始提供的类型,是一种在异常时可以帮助避免资源泄漏的智能指针。采用独占式拥有,意味着可以确保一个对象和其相应的资源同一时间只被一个 pointer 拥有。一旦拥有着被销毁或编程 empty,或开始拥有另一个对象,先前拥有的那个对象就会被销毁,其任何相应资源亦会被释放。

  • unique_ptr 用于取代 auto_ptr
auto_ptr

被 c++11 弃用,原因是缺乏语言特性如 “针对构造和赋值” 的 std::move 语义,以及其他瑕疵。

auto_ptr 与 unique_ptr 比较
  • auto_ptr 可以赋值拷贝,复制拷贝后所有权转移;unqiue_ptr 无拷贝赋值语义,但实现了move 语义;
  • auto_ptr 对象不能管理数组(析构调用 delete),unique_ptr 可以管理数组(析构调用 delete[] );

强制类型转换运算符

MSDN . 强制转换运算符

static_cast

  • 用于非多态类型的转换
  • 不执行运行时类型检查(转换安全性不如 dynamic_cast)
  • 通常用于转换数值数据类型(如 float -> int)
  • 可以在整个类层次结构中移动指针,子类转化为父类安全(向上转换),父类转化为子类不安全(因为子类可能有不在父类的字段或方法)

向上转换是一种隐式转换。

dynamic_cast

  • 用于多态类型的转换
  • 执行行运行时类型检查
  • 只适用于指针或引用
  • 对不明确的指针的转换将失败(返回 nullptr),但不引发异常
  • 可以在整个类层次结构中移动指针,包括向上转换、向下转换

const_cast

  • 用于删除 const、volatile 和 __unaligned 特性(如将 const int 类型转换为 int 类型 )

reinterpret_cast

  • 用于位的简单重新解释
  • 滥用 reinterpret_cast 运算符可能很容易带来风险。除非所需转换本身是低级别的,否则应使用其他强制转换运算符之一。
  • 允许将任何指针转换为任何其他指针类型(如 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转换,但其本身并不安全)
  • 也允许将任何整数类型转换为任何指针类型以及反向转换。
  • reinterpret_cast 运算符不能丢掉 const、volatile 或 __unaligned 特性。
  • reinterpret_cast 的一个实际用途是在哈希函数中,即,通过让两个不同的值几乎不以相同的索引结尾的方式将值映射到索引。

bad_cast

  • 由于强制转换为引用类型失败,dynamic_cast 运算符引发 bad_cast 异常。

bad_cast 使用

try {      Circle& ref_circle = dynamic_cast<Circle&>(ref_shape);   }  catch (bad_cast b) {      cout << "Caught: " << b.what();  } 

运行时类型信息 (RTTI)

dynamic_cast

  • 用于多态类型的转换

typeid

  • typeid 运算符允许在运行时确定对象的类型
  • type_id 返回一个 type_info 对象的引用
  • 如果想通过基类的指针获得派生类的数据类型,基类必须带有虚函数
  • 只能获取对象的实际类型

type_info

  • type_info 类描述编译器在程序中生成的类型信息。此类的对象可以有效存储指向类型的名称的指针。type_info 类还可存储适合比较两个类型是否相等或比较其排列顺序的编码值。类型的编码规则和排列顺序是未指定的,并且可能因程序而异。
  • 头文件:typeinfo

typeid、type_info 使用

#include <iostream>using namespace std;class Flyable                       // 能飞的{public:    virtual void takeoff() = 0;     // 起飞    virtual void land() = 0;        // 降落};class Bird : public Flyable         // 鸟{public:    void foraging() {...}           // 觅食    virtual void takeoff() {...}    virtual void land() {...}    virtual ~Bird(){}};class Plane : public Flyable        // 飞机{public:    void carry() {...}              // 运输    virtual void takeoff() {...}    virtual void land() {...}};class type_info{public:    const char* name() const;    bool operator == (const type_info & rhs) const;    bool operator != (const type_info & rhs) const;    int before(const type_info & rhs) const;    virtual ~type_info();private:    ...};void doSomething(Flyable *obj)                 // 做些事情{    obj->takeoff();    cout << typeid(*obj).name() << endl;        // 输出传入对象类型("class Bird" or "class Plane")    if(typeid(*obj) == typeid(Bird))            // 判断对象类型    {        Bird *bird = dynamic_cast<Bird *>(obj); // 对象转化        bird->foraging();    }    obj->land();}int main(){ Bird *b = new Bird(); doSomething(b); delete b; b = nullptr; return 0;}

⭐️ Effective

Effective C++

  1. 视 C++ 为一个语言联邦(C、Object-Oriented C++、Template C++、STL)
  2. 宁可以编译器替换预处理器(尽量以 constenuminline 替换 #define
  3. 尽可能使用 const
  4. 确定对象被使用前已先被初始化(构造时赋值(copy 构造函数)比 default 构造后赋值(copy assignment)效率高)
  5. 了解 C++ 默默编写并调用哪些函数(编译器暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符、析构函数)
  6. 若不想使用编译器自动生成的函数,就应该明确拒绝(将不想使用的成员函数声明为 private,并且不予实现)
  7. 为多态基类声明 virtual 析构函数(如果 class 带有任何 virtual 函数,它就应该拥有一个 virtual 析构函数)
  8. 别让异常逃离析构函数(析构函数应该吞下不传播异常,或者结束程序,而不是吐出异常;如果要处理异常应该在非析构的普通函数处理)
  9. 绝不在构造和析构过程中调用 virtual 函数(因为这类调用从不下降至 derived class)
  10. 令 operator= 返回一个 reference to *this (用于连锁赋值)
  11. 在 operator= 中处理 “自我赋值”
  12. 赋值对象时应确保复制 “对象内的所有成员变量” 及 “所有 base class 成分”(调用基类复制构造函数)
  13. 以对象管理资源(资源在构造函数获得,在析构函数释放,建议使用智能指针,资源取得时机便是初始化时机(Resource Acquisition Is Initialization,RAII))
  14. 在资源管理类中小心 copying 行为(普遍的 RAII class copying 行为是:抑制 copying、引用计数、深度拷贝、转移底部资源拥有权(类似 auto_ptr))
  15. 在资源管理类中提供对原始资源(raw resources)的访问(对原始资源的访问可能经过显式转换或隐式转换,一般而言显示转换比较安全,隐式转换对客户比较方便)
  16. 成对使用 new 和 delete 时要采取相同形式(new 中使用 [] 则 delete []new 中不使用 [] 则 delete
  17. 以独立语句将 newed 对象存储于(置入)智能指针(如果不这样做,可能会因为编译器优化,导致难以察觉的资源泄漏)
  18. 让接口容易被正确使用,不易被误用(促进正常使用的办法:接口的一致性、内置类型的行为兼容;阻止误用的办法:建立新类型,限制类型上的操作,约束对象值、消除客户的资源管理责任)
  19. 设计 class 犹如设计 type,需要考虑对象创建、销毁、初始化、赋值、值传递、合法值、继承关系、转换、一般化等等。
  20. 宁以 pass-by-reference-to-const 替换 pass-by-value (前者通常更高效、避免切割问题(slicing problem),但不适用于内置类型、STL迭代器、函数对象)
  21. 必须返回对象时,别妄想返回其 reference(绝不返回 pointer 或 reference 指向一个 local stack 对象,或返回 reference 指向一个 heap-allocated 对象,或返回 pointer 或 reference 指向一个 local static 对象而有可能同时需要多个这样的对象。)
  22. 将成员变量声明为 private(为了封装、一致性、对其读写精确控制等)
  23. 宁以 non-member、non-friend 替换 member 函数(可增加封装性、包裹弹性(packaging flexibility)、机能扩充性)
  24. 若所有参数(包括被this指针所指的那个隐喻参数)皆须要类型转换,请为此采用 non-member 函数
  25. 考虑写一个不抛异常的 swap 函数
  26. 尽可能延后变量定义式的出现时间(可增加程序清晰度并改善程序效率)
  27. 尽量少做转型动作(旧式:(T)expressionT(expression);新式:const_cast<T>(expression)dynamic_cast<T>(expression)reinterpret_cast<T>(expression)static_cast<T>(expression)、;尽量避免转型、注重效率避免 dynamic_casts、尽量设计成无需转型、可把转型封装成函数、宁可用新式转型)
  28. 避免使用 handles(包括 引用、指针、迭代器)指向对象内部(以增加封装性、使 const 成员函数的行为更像 const、降低 “虚吊号码牌”(dangling handles,如悬空指针等)的可能性)
  29. 为 “异常安全” 而努力是值得的(异常安全函数(Exception-safe functions)即使发生异常也不会泄露资源或允许任何数据结构败坏,分为三种可能的保证:基本型、强列型、不抛异常型)
  30. 透彻了解 inlining 的里里外外(inlining 在大多数 C++ 程序中是编译期的行为;inline 函数是否真正 inline,取决于编译器;大部分编译器拒绝太过复杂(如带有循环或递归)的函数 inlining,而所有对 virtual 函数的调用(除非是最平淡无奇的)也都会使 inlining 落空;inline 造成的代码膨胀可能带来效率损失;inline 函数无法随着程序库的升级而升级)
  31. 将文件间的编译依存关系降至最低(如果使用 object references 或 object pointers 可以完成任务,就不要使用 objects;如果能够,尽量以 class 声明式替换 class 定义式;为声明式和定义式提供不同的头文件)
  32. 确定你的 public 继承塑模出 is-a(是一种)关系(适用于 base classes 身上的每一件事情一定适用于 derived classes 身上,因为每一个 derived class 对象也都是一个 base class 对象)
  33. 避免遮掩继承而来的名字(可使用 using 声明式或转交函数(forwarding functions)来让被遮掩的名字再见天日)
  34. 区分接口继承和实现继承(在 public 继承之下,derived classes 总是继承 base class 的接口;pure virtual 函数只具体指定接口继承;非纯 impure virtual 函数具体指定接口继承及缺省实现继承;non-virtual 函数具体指定接口继承以及强制性实现继承)
  35. 考虑 virtual 函数以外的其他选择(如 Template Method 设计模式的 non-virtual interface(NVI)手法,将 virtual 函数替换为 “函数指针成员变量”,以 tr1::function 成员变量替换 virtual 函数,将继承体系内的 virtual 函数替换为另一个继承体系内的 virtual 函数)
  36. 绝不重新定义继承而来的 non-virtual 函数
  37. 绝不重新定义继承而来的缺省参数值,因为缺省参数值是静态绑定(statically bound),而 virtual 函数却是动态绑定(dynamically bound)
  38. 通过复合塑模 has-a(有一个)或 “根据某物实现出”(在应用域(application domain),复合意味 has-a(有一个);在实现域(implementation domain),复合意味着 is-implemented-in-terms-of(根据某物实现出))
  39. 明智而审慎地使用 private 继承(private 继承意味着 is-implemented-in-terms-of(根据某物实现出),尽可能使用复合,当 derived class 需要访问 protected base class 的成员,或需要重新定义继承而来的时候 virtual 函数,或需要 empty base 最优化时,才使用 private 继承)
  40. 明智而审慎地使用多重继承(多继承比单一继承复杂,可能导致新的歧义性,以及对 virtual 继承的需要,但确有正当用途,如 “public 继承某个 interface class” 和 “private 继承某个协助实现的 class”;virtual 继承可解决多继承下菱形继承的二义性问题,但会增加大小、速度、初始化及赋值的复杂度等等成本)
  41. 了解隐式接口和编译期多态(class 和 templates 都支持接口(interfaces)和多态(polymorphism);class 的接口是以签名为中心的显式的(explicit),多态则是通过 virtual 函数发生于运行期;template 的接口是奠基于有效表达式的隐式的(implicit),多态则是通过 template 具现化和函数重载解析(function overloading resolution)发生于编译期)
  42. 了解 typename 的双重意义(声明 template 类型参数是,前缀关键字 class 和 typename 的意义完全相同;请使用关键字 typename 标识嵌套从属类型名称,但不得在基类列(base class lists)或成员初值列(member initialization list)内以它作为 base class 修饰符)
  43. 学习处理模板化基类内的名称(可在 derived class templates 内通过 this-> 指涉 base class templates 内的成员名称,或藉由一个明白写出的 “base class 资格修饰符” 完成)
  44. 将与参数无关的代码抽离 templates(因类型模板参数(non-type template parameters)而造成代码膨胀往往可以通过函数参数或 class 成员变量替换 template 参数来消除;因类型参数(type parameters)而造成的代码膨胀往往可以通过让带有完全相同二进制表述(binary representations)的实现类型(instantiation types)共享实现码)
  45. 运用成员函数模板接受所有兼容类型(请使用成员函数模板(member function templates)生成 “可接受所有兼容类型” 的函数;声明 member templates 用于 “泛化 copy 构造” 或 “泛化 assignment 操作” 时还需要声明正常的 copy 构造函数和 copy assignment 操作符)
  46. 需要类型转换时请为模板定义非成员函数(当我们编写一个 class template,而它所提供之 “与此 template 相关的” 函数支持 “所有参数之隐式类型转换” 时,请将那些函数定义为 “class template 内部的 friend 函数”)
  47. 请使用 traits classes 表现类型信息(traits classes 通过 templates 和 “templates 特化” 使得 “类型相关信息” 在编译期可用,通过重载技术(overloading)实现在编译期对类型执行 if…else 测试)
  48. 认识 template 元编程(模板元编程(TMP,template metaprogramming)可将工作由运行期移往编译期,因此得以实现早期错误侦测和更高的执行效率;TMP 可被用来生成 “给予政策选择组合”(based on combinations of policy choices)的客户定制代码,也可用来避免生成对某些特殊类型并不适合的代码)
  49. 了解 new-handler 的行为(set_new_handler 允许客户指定一个在内存分配无法获得满足时被调用的函数;nothrow new 是一个颇具局限的工具,因为它只适用于内存分配(operator new),后继的构造函数调用还是可能抛出异常)
  50. 了解 new 和 delete 的合理替换时机(为了检测运用错误、收集动态分配内存之使用统计信息、增加分配和归还速度、降低缺省内存管理器带来的空间额外开销、弥补缺省分配器中的非最佳齐位、将相关对象成簇集中、获得非传统的行为)
  51. 编写 new 和 delete 时需固守常规(operator new 应该内涵一个无穷循环,并在其中尝试分配内存,如果它无法满足内存需求,就应该调用 new-handler,它也应该有能力处理 0 bytes 申请,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”;operator delete 应该在收到 null 指针时不做任何事,class 专属版本则还应该处理 “比正确大小更大的(错误)申请”)
  52. 写了 placement new 也要写 placement delete(当你写一个 placement operator new,请确定也写出了对应的 placement operator delete,否则可能会发生隐微而时断时续的内存泄漏;当你声明 placement new 和 placement delete,请确定不要无意识(非故意)地遮掩了它们地正常版本)
  53. 不要轻忽编译器的警告
  54. 让自己熟悉包括 TR1 在内的标准程序库(TR1,C++ Technical Report 1,C++11 标准的草稿文件)
  55. 让自己熟悉 Boost(准标准库)

More Effective c++

  1. 仔细区别 pointers 和 references(当你知道你需要指向某个东西,而且绝不会改变指向其他东西,或是当你实现一个操作符而其语法需求无法由 pointers 达成,你就应该选择 references;任何其他时候,请采用 pointers)
  2. 最好使用 C++ 转型操作符(static_castconst_castdynamic_castreinterpret_cast
  3. 绝不要以多态(polymorphically)方式处理数组(多态(polymorphism)和指针算术不能混用;数组对象几乎总是会涉及指针的算术运算,所以数组和多态不要混用)
  4. 非必要不提供 default constructor(避免对象中的字段被无意义地初始化)
  5. 对定制的 “类型转换函数” 保持警觉(单自变量 constructors 可通过简易法(explicit 关键字)或代理类(proxy classes)来避免编译器误用;隐式类型转换操作符可改为显式的 member function 来避免非预期行为)
  6. 区别 increment/decrement 操作符的前置(prefix)和后置(postfix)形式(前置式累加后取出,返回一个 reference;后置式取出后累加,返回一个 const 对象;处理用户定制类型时,应该尽可能使用前置式 increment;后置式的实现应以其前置式兄弟为基础)
  7. 千万不要重载 &&|| 和 , 操作符(&& 与 || 的重载会用 “函数调用语义” 取代 “骤死式语义”;, 的重载导致不能保证左侧表达式一定比右侧表达式更早被评估)
  8. 了解各种不同意义的 new 和 delete(new operatoroperator newplacement newoperator new[]delete operatoroperator deletedestructoroperator delete[]
  9. 利用 destructors 避免泄漏资源(在 destructors 释放资源可以避免异常时的资源泄漏)
  10. 在 constructors 内阻止资源泄漏(由于 C++ 只会析构已构造完成的对象,因此在构造函数可以使用 try…catch 或者 auto_ptr(以及与之相似的 classes) 处理异常时资源泄露问题)
  11. 禁止异常流出 destructors 之外(原因:一、避免 terminate 函数在 exception 传播过程的栈展开(stack-unwinding)机制种被调用;二、协助确保 destructors 完成其应该完成的所有事情)
  12. 了解 “抛出一个 exception” 与 “传递一个参数” 或 “调用一个虚函数” 之间的差异(第一,exception objects 总是会被复制(by pointer 除外),如果以 by value 方式捕捉甚至被复制两次,而传递给函数参数的对象则不一定得复制;第二,“被抛出成为 exceptions” 的对象,其被允许的类型转换动作比 “被传递到函数去” 的对象少;第三,catch 子句以其 “出现于源代码的顺序” 被编译器检验对比,其中第一个匹配成功者便执行,而调用一个虚函数,被选中执行的是那个 “与对象类型最佳吻合” 的函数)
  13. 以 by reference 方式捕获 exceptions(可避免对象删除问题、exception objects 的切割问题,可保留捕捉标准 exceptions 的能力,可约束 exception object 需要复制的次数)
  14. 明智运用 exception specifications(exception specifications 对 “函数希望抛出什么样的 exceptions” 提供了卓越的说明;也有一些缺点,包括编译器只对它们做局部性检验而很容易不经意地违反,与可能会妨碍更上层的 exception 处理函数处理未预期的 exceptions)
  15. 了解异常处理的成本(粗略估计,如果使用 try 语句块,代码大约整体膨胀 5%-10%,执行速度亦大约下降这个数;因此请将你对 try 语句块和 exception specifications 的使用限制于非用不可的地点,并且在真正异常的情况下才抛出 exceptions)
  16. 谨记 80-20 法则(软件的整体性能几乎总是由其构成要素(代码)的一小部分决定的,可使用程序分析器(program profiler)识别出消耗资源的代码)
  17. 考虑使用 lazy evaluation(缓式评估)(可应用于:Reference Counting(引用计数)来避免非必要的对象复制、区分 operator[] 的读和写动作来做不同的事情、Lazy Fetching(缓式取出)来避免非必要的数据库读取动作、Lazy Expression Evaluation(表达式缓评估)来避免非必要的数值计算动作)
  18. 分期摊还预期的计算成本(当你必须支持某些运算而其结构几乎总是被需要,或其结果常常被多次需要的时候,over-eager evaluation(超急评估)可以改善程序效率)

转自:https://mp.weixin.qq.com/s/GOk0jlbJPl9NNtXmdLz9WQ

男子从殡仪馆打来电话:能不能写写我们的天才儿子

写在前面

阳光很好的一天,金晓宇陪着父亲来报社送照片。目送他们远去的背影,我想到,站在眼前的是一个天才翻译家和他的父亲。

了解他们的故事,你会潸然泪下。这诚然是一个悲伤的故事,但也洋溢着坚韧不拔的爱,无法被摧毁的爱。爱能催生出强大无比的意志,能承受生活沉重的压力。只有父爱才能让一个父亲坚信自己的孩子,不放弃自己的孩子。这个承诺不是一年两年,而是永远、永远。
在命运面前,在不幸面前,一个家庭就像一艘漂泊的小船,劈波斩浪,沉浮与共。我们相信,这艘小船最终能在一个巨大的港湾找到容身之所,会有安定的生活。

以下,是金晓宇父亲金性勇的自述

2021年11月11日上午,我在杭州殡仪馆放好了老伴的骨灰盒,感觉自己手发颤,走路腿也抖。我让几个亲友先走,我还想陪她一会。
老伴脑子清醒时曾跟我说,哪天她走了,骨灰盒先放殡仪馆里,以后是安葬还是洒到江里海里,要等大儿子回家再决定怎么处理。
但我没有打电话给金晓天,现在全世界疫情,他回不来。也没有告诉金晓宇,11月之前他就住院了。
让孩子们以为妈妈还活着吧。
我望着那个盒子,和老伴说:我要打电话了,你同意吧?哪天我也走了,就没有人知道我们儿子的事了。
我从挂在手腕上的小包里,摸出老年手机和一张《杭州日报》。报头上有我抄的“倾听·人生”的电话号码。电话接通了。我说:“你们能不能写我儿子的故事?我儿子是天才,他现在精神病院里,他妈妈今天刚走了。”

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇和父亲金性勇
6岁那年,玩伴的玩具手枪里射出一根针

我儿子的一只眼睛就此瞎了

我的老家在浙江桐乡,父亲是小学校长,老伴的妈妈,那时候是我的老师。我们两家住在同一个门头里,算得上青梅竹马。
我老伴叫曹美藻。我考进了上海化工学院,美藻考到了南京大学化学系。毕业后,同分配到天津工作。1967年我们结婚了,先是生了大儿子金晓天,1972年又生了小儿子金晓宇。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇童年时的家庭合影
1984年,我们带着两个儿子落叶归根回到杭州。这么执意回来是因为心里扎进一根剌,万想不到它变成了一把刀。小宇的命怎么会这么苦?
在天津时,我们住集体宿舍,一间房十五六平米。六岁那年,小宇和邻居孩子一起玩,那孩子手里有一把玩具手枪,可以放小纸球射出来。万没想到那天他放了一根针,一枪打到小宇眼睛里,左眼晶体碎了。
小宇的一只眼睛从此瞎了,只能斜眼看东西。他还反过来安慰我们:没关系,习惯了。
两个儿子都聪明。回杭州后,大儿子考进复旦大学,后来考托福去了澳大利亚。小宇高一时分在尖子班,老师说考大学完全没问题。但有一天,小宇突然和我们说:“我不上大学了,也不要读高中了。”
高中时他突然厌学,情绪大变

家里的电器被他砸了个遍

我们以为小孩子厌学说说玩的,可他真的天天赖在家里。我让朋友帮忙,介绍小宇去解放路新华书店当售货员。我想,过段时间孩子就想回学校了。
两个月不到,书店不要他了。起因是有位老顾客在店里看书,小宇说人家是小偷,争执起来。我又把小宇介绍到排气扇厂当工人,没几天他就不肯上班,说那些工友对他不好。
他不上学后,我和他妈每天上班走之前,他在床上,下班回家,他还在床上。他也不跟我们说话,会突然发脾气,情绪极不稳定,完全变了一个人。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇少年时和父亲的合影
有一天,我和他妈妈坐在沙发上看电视,轰隆一声巨响。小宇把厨房的冰箱推倒了。这是他第一次出现暴力行为。
因为这,我们家一直“家徒四壁”。全杭州可能就我家没有电视机,之前被小宇砸坏了三个,往里面灌水。冰箱、洗衣机换过好几个了,还有桌子、书架、柜子、门……好好的,突然轰一声,你说怎么办?
小宇妈妈绝望地问我:“他是疯了吗?”

 

考上了大学,他还是没能留下来

医生说,我儿子是躁狂抑郁症

很长时间,我们不知道孩子这是生病了。当他说想考大学,我们喜出望外,让他进了补习班。小宇高中基本没上过,几个月后,高考成绩让人吃惊,离一本线只差3分。
二本志愿填了杭大外语系,分数也超线了。我们很开心地等学校通知。谁知学校将档案退回,档案里记录了小宇高中时不守纪律、缺课。
七转八转,小宇进了树人大学,可是只读了一年就犯病了。据同学讲,他们几个到外面喝酒,小宇表现得异常兴奋,回校后还往老师的汽车顶上爬,拉都拉不住。
学校以为是发酒疯,把他送到医院。小宇看到我,很愤怒,“你来干什么?把针头拔掉,我要回家!”
我把他带回家。我知道这孩子与学校从此无缘了。

男子从殡仪馆打来电话:能不能写写我们的天才儿子金性勇

有两年,他埋头自学,比上学还用功。两年后,他拿到了浙江大学英语系的自考毕业文凭。
但接着发生了可怕的事,当时我不在家。小宇睡在床上怎么也叫不醒,他妈发现他是吃了安眠药自杀,赶紧和邻居把他送到医院洗胃。幸亏药量不足,孩子救了回来。
又过了段时间,我们听到哗啦一声响,冲进房间看到小宇摔在地上,一圈皮带挂在天花板吊灯和窗户之间。我和他妈抱着他哭,“孩子,你不要做傻事啊!”
我是研究医药化工的,孩子这些表现不是性格问题了,我就看书找原因,小宇的症状符合精神类疾病。去几家医院看了,都诊断是躁狂抑郁症,也叫双相情感障碍,病人会抑郁和躁狂交替发作。小宇不上学,情绪低落,晚上不睡觉,甚至自杀,这些都是在抑郁期;无端猜疑指责别人,狂躁不安,有破坏行为,是转入了躁狂期。

 

不读书不工作不成家都能接受

我们只要儿子活着

精神科专家说这病来得快去得快,危险就在于不知道什么时候来什么时候去,吃药也不能控制,唯一能做的就是及时送医院。1992年起,基本每年都要送小宇进去。
我买了很多精神疾病的书看。最后有两点让一个父亲不至于崩溃:一是通常这类病人一两次自杀未遂后很少再有这个念头,他们会比之前珍惜生命;二是这类病人会在精神领域不同凡响,甚至表现出天才性的创造力。
我读到一本书叫《躁狂抑郁多才俊》,是美国一名精神病医师写的,里面列举了25位历史名人:贝多芬、梵高、牛顿、海明威……他们终其一生都有双相情感障碍的典型表现,承受了超出常人的痛苦。又都是具有伟大想象力的天才艺术家。
懂得这些知识后,我最大的宽慰就是小宇可能不会再自杀了。至于“天才”,我没去想过,毕竟不是所有精神病人都能成为梵高、牛顿,即使成了天才也需要两点:一是活着,二是机遇。
儿子不想死了,我和他妈忽然觉得什么都不重要了,不读书不上大学不工作不成家,我们都能接受——只要他活着。
指责别人,狂躁不安,有破坏行为,是转入了躁狂期。

 

老伴的一场同学会改变了他的命运

“能不能请你儿子在家做翻译”

又过了十年,2010年,老伴去南大开50周年同学会。也许是天怜英才,也许是一个母亲的精诚所至,这场同学会竟然改变了小宇接下来的命运。
听说我家孩子因病没有工作,一位留校做了教授的同学就问她:能不能请你儿子在家做翻译?
我老伴说,小宇的英语日语都很好,请给他一个机会试试吧。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

小宇家的电脑
时光回到上世纪90年代,那是我们家最困难的时期,到处治病要花钱,孩子出门闯祸要赔钱,但我还是竭尽所能满足小宇的要求。他最大的要求就是买书——英语、日语、古文、围棋、音乐、绘画、地理等,各种书籍买了两百多本。
1993年,我冒着被砸坏的风险,花一万两千块钱给小宇买了一台电脑。小宇那天高兴地说:“爸爸,谢谢你!”
之后,他发病时也摔过东西,但从不碰电脑。电脑成了小宇的另一个世界。他也不玩游戏,主要就做两件事:自学外语、看原声电影。他用了六年时间自学了德语、日语,巩固英语。看外语电影,他先看带中文字幕的,看懂后,做一个纸条挡住字幕再看。一部电影反复看N遍,直到完全听懂。
这一切给小宇带来的兴奋和投入,是孩子在躁狂期创造力增强的表现。“机会总是给有准备的人”,我从没想过这句话跟小宇有什么关系。直到十年后,他妈妈开同学会回来,我才忽然觉得,这些年和孩子一起经历的事,就像是一个训练营——
原来,机会真的是给每一个有准备的人。
南大出版社很快寄来了美国女作家安德烈娅·巴雷特的八个短篇小说,让小宇翻一篇试试。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇的首部翻译作品《船热》
他以最快速度翻译了其中一篇《船热》。交稿时跟出版社说,如果审核通过,剩下的也请交给我翻。
我很惊讶,这是文学啊,翻译等于再创作,一篇还不知道行不行,一整本书你能翻译好吗?
小宇说,行的,爸爸你放心,我翻的不会比别人差,这些年我出门就是到浙江图书馆,我不是去玩,你到浙图查下借阅登记卡,我借过的每本书,都有金晓宇的名字。
“那你看过几本小说?”
“我看完了图书馆里所有的外语小说。”

 

十年里,他翻译了22本书

老伴同学说:你们养了一个天才!

时间回到2010年,小宇接受了出版社的任务,开始他的翻译人生。十年里,小宇以每年两本书的速度,一共翻译了22本书。他短暂又高产的翻译生涯,是我们全家最难得最幸福的岁月。
2013年,小宇翻译出版了爱尔兰作家约翰·班维尔的英文小说《诱惑者》。原书名《Mefisto》,小宇和编辑讨论时,对方说这个没法意译,用音译吧,就是《梅菲斯特》。但小宇知道,Mefisto是歌德代表作《浮士德》里的角色,这个人物就是一个诱惑者,那么可能诱惑者才是作者的本意。小宇决定采用《诱惑者》作书名,结果出版社非常赞赏,《诱惑者》也成为抢手好书。
翻译日本女作家多和田叶子的小说《狗女婿上门》时,小宇天天看日本相扑比赛,为了提升翻译的准确度。屏幕下方,挡字幕的纸条飞舞。屏幕上,两个只系着腰带的大力士在翻滚打斗。我们父子俩看得哈哈大笑。小宇先后翻译了多和田叶子的五本小说,反响都很好,出版社打算再出合订本。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

再比如《安德烈·塔可夫斯基:电影的元素》,这本书非常难译,小宇专门去看了塔可夫斯基导演的所有电影。南大选派了外国文学专业的顾老师担任本书责编,顾老师又邀请本书作者罗伯特·伯德的博士研究生彭欣为小宇译著撰写了附录。这本书2018年出版,影响很大,网站有电影研究者发文说,“原以为金晓宇译文有错误,特意买了原著对照看,才知道金译没有错,而且比原文还好,文字更细腻……”
孩子一生没有朋友。我作为父亲,最有幸的是在这十年成为孩子最好的朋友、助手。我买了扫描仪、打印机,跑邮政帮他收外文样稿,买资料书,翻译完给他打印样稿,译文每本都是几百页,小山堆一样,再帮他校稿、寄出样书……每本书从样稿到出版,我都是第一读者。惊喜的是我从没看到过一个错字,22本书、近七百万字,你说我不容易?是小宇更不容易啊!
编辑部负责人来我家看过小宇,他说金晓宇译的书稿寄到编辑部,大家都抢着做责任编辑,因为全书没有错字、错句、错译,每本书都好卖,读者反响很好。
南大同学打电话祝贺孩子妈妈,“你们养了一个天才!”

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇的翻译作品横跨小说、电影、音乐、哲学多个领域
但除了南大,翻译界没人知道金晓宇是谁,社会上没人知道我儿子到底付出了多少心血,更没人知道这些书是一个躁郁症患者翻译的。从没露出过笑脸的小宇,第一次眉开眼笑地告诉我:“爸爸,浙江图书馆里也有我翻译的书,我还特意去查了借书登记本,有很多读者借过金晓宇译的书哦!”
新书出版后,小宇会去查看豆瓣评分,“爸爸,爸爸,都是8分以上,还有很多读者评论好看……”
我一句话也说不出来,只笑着点头,“好、好”。

 

儿子步入正轨,但老伴的身体撑不住了

痴呆这几年,儿子天天照顾她

老伴这一生过得很辛苦,她当年是高材生,有文化有专业,她勤劳节俭,全家人四季衣服都是自己做的。小宇不知砸坏了多少东西,妈妈的缝纫机他从不砸。
2000年前后,老伴开始炒股。我们分工默契,我在家守儿子,她每天去证券交易所。我明白她炒股是为小宇存钱,从孩子童年瞎了一只眼后,她的心就扑在小宇身上。后来小宇的病让我们毫无办法,她的绝望无奈都埋在心里了。小宇在家翻译,让她看到一丝光亮,但她自己这盏灯却要灭了。
2015年,老伴说自己记性不好,不炒股了,要把存款都交待给我。我这才知道她有200万元的理财产品拿不回来,我想尽办法追回款子,还是有50万元丢了。这件事后老伴的健康每况愈下,之后确诊得了阿尔茨海默症,接着日常生活不能自理,在床上躺了三年。
小宇非常难过,他说我能翻译书是妈妈的功劳。每次出版社寄十本样书给小宇,他都第一时间冲到床边送到妈妈手里,讲给妈妈听。后来,他妈妈开始不会说话、不认得家人。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

金晓宇少年时的家庭合影
古话说,久病床前无孝子,但我儿子就是真孝子。妈妈痴呆了好几年,他从没对妈妈发过脾气,还为妈妈做了很多事。白天他照顾妈妈,负责买菜,每天买妈妈喜欢吃的虾,饭后洗碗,再给老妈洗脸。我管晚上的事,做三餐饭,给老伴剥虾喂饭。
他妈妈三年没上过厕所,每两小时要接一次大小便。先前她的脚还有力气,抱她坐到床边一个便桶椅上,后来只能抱着拖拽下来。我80岁了,真抱不动,幸亏有小宇。没有小宇,我们可能都死了。
小宇很仔细很耐心,有时小宇做这些事时,他妈妈的眼里有泪。每天小宇抱着妈妈喊“老妈啊,老妈啊”。他心里记着妈妈的恩,从六岁剩下一只眼,妈妈就为他流泪,抱着他不知哭了多少次。我心里想说,儿子啊,你长大后更是不知妈妈为你哭过多少次啊。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

这三年,我真正明白了什么叫相依为命,这三年也是小宇翻译冲刺时期,除了南大,别的出版社也找他翻译了,书一本比一本厚。孩子的病症也奇迹般减少,照顾妈妈,日夜翻书,小宇一直很安静很努力,直到去年11月。
小宇的第22本是德文书。早在2016年,他就接到出版社约稿,请他翻译德国思想家本雅明的《书信集》。这本书有53万字。拿到德文书稿后,小宇通宵达旦查阅资料,连发病都忘了,只用一年时间就交出译稿。
可惜,因为出版社的原因,这本书迟迟没能出版。小宇天天在等。
这些年我们非常感谢社区、感谢湖墅派出所、拱墅区残联、侨联的照顾,让我儿子能够健康地走向社会、为社会做更多贡献。
这些年也有人不理解,说我要儿子搞翻译是为了挣钱,我只有苦笑。他们不知道翻译根本不挣钱,新书只是我儿子命悬一线时的强心剂。

 

儿子不带手机一个人去了温州

他回家后若无其事,我却心里一紧

书久等不见,我最担心的事还是发生了,去年11月之前小宇跑到温州去了。
每年11月到第二年3月,是小宇最难熬的日子。去年10月,儿子已经很久没出门。这天吃过晚饭六点钟,他说:“爸,晚上药我吃过了,不会走远,7点肯定回来。”我叮嘱他早点回家,别的不敢多问。
小宇出门从来不带手机,7点、8点、9点……11点,我急了,跑到派出所报案。
过去他在马路上瞎晃,民警碰到都会带他回来。第二天,民警查监控,发现小宇晚上乘151路到了城站火车站,买了去温州的票。他身上可能有一百多块钱。
我急得团团转,小宇却回家了。问他去温州干什么,他说下车吃了点东西就回来了。看他若无其事,我心里叫苦,这是躁狂症发病的前兆啊。
又过了几天,小宇过马路,迎面一个快递员,他一拳打掉了人家的门牙……不久,七院来人,将小宇带走。儿子呼天喊地:爸爸救救我,我不去医院啊,不要去啊。
一个晚上,老伴走了

我什么都不能为她做了

11月8日晚上,我像平常一样睡前摸老伴的额头、脸,再去摸脚。怕她冷了、热了,摸了才知道。
这天,我摸哪里都是寒的,脚像冰块一样。我赶紧开空调,打到25度,又抱了一床毯子加在被子上。过半小时再摸,还是没有一丝热气。
我慌了,抱着她的头靠在怀里,“靠牢我靠牢我”,我脸贴着脸,但还是越来越冷。“你不能走,不能走啊!”,我把脸贴得更近,手哆嗦着摸她的鼻子,没气了,往下摸,心脏不跳了。
我不知道怎么办,完全没有思想准备。她走了,我儿子没有妈妈了。

男子从殡仪馆打来电话:能不能写写我们的天才儿子

我还在计划给老伴做插管手术,有个90多岁的邻居也是这个情况,做了手术还活着。我为什么没早点给她做呢?这一夜我守着老伴越来越冷的身体,流泪,自责,后悔。
虽然她早就不认识我,早就什么都不知道,但我知道她还活着,知道我每天是为她、为儿子活着。她走了,我没有一丝一毫的解脱。我已经习惯她活着,习惯天天为她做事。三年来我睡她床横头的沙发,晚上我能听见她的呼噜声、呼吸声、咳嗽声……我像钟表一样准时,两小时准会醒来,跟她说话,给她翻身,喂她喝水……现在这么安静,什么都听不到了,什么都不能做了。
上周我去医院看过小宇,给他送点吃的。每次去那里看他,每次都听他哭叫,“求求你带我回家,爸爸我们回家吧……”
儿子春天会回来,他会让妈妈看他的新书。
《本雅明书信集》终于寄来了。
 
最新消息
金晓宇85岁父亲金性勇老人告诉记者:小宇已经出院回家,等待已久的《本雅明书信集》样书也已收到,预计下月上市。目前他正在全力翻译第二本本雅明的著作《拱廊计划》。老人感谢了大家的关心,但也婉拒了所有物质帮助。
 
来源:杭州日报

监制:张越

编辑:周喆、李昂、王宜玄、王朝

实习:孙誉宁、满兴莲、马如玥

转自:https://mp.weixin.qq.com/s/tdyrzM71OVDuFvlb52gd0A

 

我卧底了一家中介门店,背后看到…

之前一个周末,我跟一个中介朋友约饭,他迟到了
他说周末比较忙,忙着“练”房东呢…
 
没想到这年头还能听到这个词
现在都怎么“练”呢,他说先跟房东说今天会有客户来看房,看好了就能订,然后雇假客户去看房,最后约房东到门店谈价格
我卧底了一家中介门店,背后看到…
当然不是真谈价格,而是要看看房东的心里价位,顺便压压价格,促成交,这就是摸底、排雷和试六大项,对外叫面谈,内部代号“MT”
类似这样的代号还不少,用起来方便,被房东看到也没事,谁能看懂
我卧底了一家中介门店,背后看到…
是不是还挺小心机的,中介朋友考我说:跟进,EK,以ZY名义消极房东,这句什么意思
 
没想到一个门店背后还有那么多套路,为了获得更多内幕,我准备去卧室一家中介门店,去看看背后到底是怎么运作的
没想到,真的进入之后发现足够的魔幻
 
记录了一些工作笔记,大概有这一些……
01
“布点、跟踪、穿插、游击”
如果非说小心机的话,他首推找客户这件事
简单说就是:布点、跟踪、穿插、游击
每个门店都会有自己深耕的小区,每天早9点到晚上7点半,小区门口永远有附近中介门店的一个人在门口发传单
每周末会在小区正门、后门、所有进出口上布点,只要有一个中介来带看,他都了如指掌
如果有别家中介带着客户从一个小区到另一个小区,群里也会奔走相告,看看隔壁小区有没有人,没人的话,派人去支援
支援过去做的都是一件事,跟踪
看你进小区左拐还是右拐,都知道你去看的是哪套房,小区里在卖的房他们几乎门儿清
我卧底了一家中介门店,背后看到…
进小区右转了,那就一定是8号楼1单元501,于是就派小哥穿插到别家中介前面等着他们,或者直接到楼里面等,这叫穿插
一般来讲,别家中介和客户进了这栋楼,穿插中介都不会让你发现,大概你们进去4、5秒他才会刷卡进去,然后在7楼、8楼的楼梯拐角处那里猫着听动静
穿插不是为了当面截胡,而是伺机而动
中介和客户总有分开的时候,只要你跟的不紧,那我就中场截胡,如果到小区门口才分开,我就到小区门口等你们分开后,再上去问一句
“姐,我看您刚看的两房,我这有一套同小区的,要不要看看”
就算客户去地铁,我跟进地铁行不行,如果开车更好办,就会有泊车电话,前面步骤全部省略,直接电话问要不要看更多一套房源
泊车电话要不到,去黑车产业链查车牌,25块/个,这钱就买一个号码不便宜,但是架不住客户够精准
一般来说,开车一来就是一家人,这样现场就能做决定,如果一辆车带着老人、孩子,开着一个车,这个车还是30万以上
这种情况就说明有购买力,决策人在场,这时候什么20、25,早就不在乎这点钱了,话术都想好了
“您好,我这有一套房,也是这个小区的,是我们独家的,您还没看过,来都来了,要不要看下”
这个时候没人会拒绝,来都来了,干嘛不多一个选择,如果看中了,这就是“一枪头”
我朋友说了句励志又好笑的话,“只要有心,都是办法”
02
为了独家房源,他们可以有多拼
可以看的出来,不管是布点还是游击,前提都得是我有房源
对中介来说,只要有房,就不愁没客户,有时候一家中介公司80%成交都是来自独家房源,所以挖房源很重要,尤其是独家
一般一个门店在一个小区有2-3套独家,中介基本可以横着走,其他中介这时候往里面带看,几乎就是给独家房源的中介送客户
所以有些小中介门店挨着客户多的中介门店开也有好处,只要有独家房源,就不愁开单
我听中介朋友说过,他为了深耕一个小区的独家房源,甚至自己搬到这个小区去住
为了争取房东的好感,他们也会自己维护小区做社区服务,服务的主要内容差不多就是捡垃圾
而且一定是趁大家早上上班的时候,这时候大家正出门可以看到,白天都不在家,晚上下班时间点也不固定
不要小看这一点,做足时间差不多在半小时、一小时左右,你的业主会看到你,看着中介身上的衣服,无意中加深了一遍品牌,而且也会多点好感
足够让业主在挂牌或者卖房的时候,多想到一点点就赢了
如果得到消息说小区哪家房子挂出来的时候,小哥们就开始出动了
首先,亮家伙,我们有多少门店、多少业务员、多少刷新服务、每天被推荐多少次…
其次,软磨硬泡,每天维护、定时拜访、反复推销
还有这种烧脑的局中局
我卧底了一家中介门店,背后看到…
明明自己是s价的那个,还托底交流,大概率可以赢得信任,拿到独家
不得不再感叹下,没想到现在中介都已经把活做的这么细了
03
“记住,无状况不成交”
中介朋友说,他带客户去看房,基本都会安排状况
到楼下会遇到第一个状况
我卧底了一家中介门店,背后看到…
其实这时候根本没客户
往里进,电梯下来了,一个中介带着老太太
我卧底了一家中介门店,背后看到…
老奶奶是雇的
到门口了,被堵门了
我卧底了一家中介门店,背后看到…
当然了,还是没客户
到这还不是全剧最高潮,等你到房子里面正在看房的时候,这时候会有人冲出来,气势汹汹的对你的中介说
我卧底了一家中介门店,背后看到…
一通下来,一个真客户都没有,就你自己
是不是觉得这是很久之前才会发生的事,其实就算是现在,这种情况依然有
这些“小剧场”,就是一个个“状况”,对中介来说,无状况不成交
而且如果中介不这么做,尤其复看的时候无状况,回到门店就会被批一顿
如果在你看完一套房,犹豫墨迹不能决定的时候,不走又不定,这时候业务员就会给店长打电话,或者直接在群里扣数字
扣1后,店长电话就来了 
我卧底了一家中介门店,背后看到…
如果赶上周末,还得扣2
我卧底了一家中介门店,背后看到…
这时候可能全店的人都屋里待着呢,想要的效果就是现在市场太好了,如果市场不好,那是别的区的事,我们这不存在
扣3,功能更高级,那边就不再是经纪人,可能是房东
我卧底了一家中介门店,背后看到…
话说到这就两个结果,同意加就加5w,不能加,那就给你推荐一套一样好的,再不买就没那么走运了
最后整体效果就是,这个市场很好,你最好赶紧买
04
中介为什么这么拼
为什么那么想抢独家、抢客户、促成交
我问我那位中介朋友,干嘛这么拼,安安静静做一个中介不好么
他说我也不想,上传信息、带看、客户维护、驻守,这些都是量化考核,没达标就罚钱,还有体罚
一般的指标没有达成的话,男生就罚30-50个俯卧撑,女生就是30-50个深蹲
罚的比较严重的就是长跑或者爬楼,20多层楼,两上两下,有的区域楼层比较高的30多层就运气不太好了
不过运气最差的是,区域楼层都低,那就只能去爬区域商业写字楼,层高4m,普通居民楼的1倍多
平时忙也没关系,可以下班后罚,跑完打卡下班
每周开店长会的时候,没有找到独家房源就要“仰望”,就是在别家店长做分享的时候,在旁边迈开弓子布微微抬头仰望对方
十几二十个店长分享起来,一通分享下来至少50分钟,如果后面第二周还没有,就举灭火器仰望
这样一套奖罚激励制度下来,团队只能拼了,手段也出来了,小心机也出来了
不光二手房,新房也是,不过故事都发生在积分摇号前
前台、岛台、沙盘、洽谈区一套完整的流程走下来,最灵魂设置,是岛台,这里一定会安排一个靠谱的人在那坐着
如果洽谈区有一桌快要成功了,销售就会提示岛台“喊一个”,喊一个假控、或者喊一个砸蛋
 
然后,跟你说几个已经卖掉的,或者说确实不让你买的,想要的效果不是要你买,而是让你抢
 
为什么我们要这么拼…
05
其实现在市面上的中介,基本分两种
一种就是拼平台资源的,这种中介不愁客源流量、也不愁房东挂牌
还有一种就是拼人效的,流量和资源倚靠的对象更多是个人,或者说一个团队机制、一套价值体系
有时候我经常在想,未来我们更需要的是哪一种
 
以上为正文,来自巧克丽丽
 

 

转自 : https://mp.weixin.qq.com/s/bpFdGCaCzkMq8VT90A9UUg

读书很厉害的人,为什么会混得不好?

读书很厉害的人,为什么会混得不好?

 

这句话其实不对,至少不全对,实际上,读书很厉害的人在人生的上半场,有很多混得不好的,但是人生的上半场很重要,有很多优秀的人就此埋没在芸芸众生的序列中,泯然众人矣,只有极少数人能在下半场开始追赶。

 

我这样说,可能很多人现在还听不太懂,但这确实是我最近最深的感悟。

 

 

众所周知,升值计是一个有关人生规划和财富的公号,我们今天好好聊聊这个话题。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

世界上有两种智慧,书本智慧和街头智慧,book smart和street smart。

 

 

读书很厉害的人,通常是具有书本智慧的。说白了,前面十几年二十几年都在寒窗苦读,都是从书本上学到的知识和道理,是从老师、从教育体系里得来的道理。

 

书上的道理有两个麻烦,第一个麻烦,书上的东西是错的。

 

比如前几天我儿子读《说岳全传》,给我讲里面的岳飞的青龙山大战,八百破十万,说里面的计策非常高明,安排一百名士兵在某某处准备硫磺硝石,安排一百名士兵在某某处多备麻袋截断河流,等金国粘罕十万大军来到,先诱敌进入伏击圈,然后火攻,等金军要渡河之时,放开河水,顺势掩杀。

 

然后我问他,你也看过《三国演义》,那你有没有觉得,这个故事情节,跟《三国》哪一段很像?

 

他说,对,火烧博望坡。

 

我告诉他,这就是我不愿让你看《说岳全传》的道理,这些全是套路。

 

这些套路,全是落魄文人编的,写这种套路的人,一天仗没有打过,就幻想自己摇摇鹅毛扇子,就能「运筹帷幄之中,决胜于千里之外」,打仗怎么可能恰好就有一座山,给你火攻,恰好就有一条河给你截断,还要恰好天气就适合放火,恰好河水水量不大不小,而且粘罕就是要cos夏侯惇,岳飞才能cos诸葛亮,吉青cos张飞。

 

这就是很多书的问题,书本身的道理就不全对,真要当真了拿去用,自然就被现实打得一败涂地,然后就得了自闭症,这就是殷浩故事,书生掌兵,丧师辱国,躲在小黑屋画圈圈,终生就是想不明白,只能死钻牛角尖,「咄咄怪事」。

 

 

还有第二个麻烦,书上的道理都对,但是暂时用不上,这才是书本智慧的常态。

 

但是,所有人都或早或晚地进入社会,如果你不是含着金钥匙出生,那么你开始进入的就是社会的底层,当然,这个底层不是真正的底层,而是各种基层,可能有人收入高,上来年薪四五十万,但是,都是行业的基层,各种行业的基层。

 

 

基层,就有基层的问题,要解决这些问题,你会发现书上的道理没有用。书上只会教你,襟怀坦荡,对人真诚,不要拉帮结派,然后到现实中一看,你碰到的人,没有一个照着书上活的。比如,所有的教育系统都教我们,对待朋友要坦诚。但是如果你真的到了社会上,对遇到的每一个人都坦诚相待、推心置腹,那么你很快会发现,这样做会让你在社会上碰的头破血流。这就导致这些人,在适应现实的时候,会比普通没有读过书的人,有更多麻烦。

 

因为现实里的人,会动。用我喜欢说的一句话就是,你在基层碰见的,都是盐碱地人。

 

但是,你要知道,如果一个人在人生的头二十多年,顺风顺水,适应一个规则适应得非常好,那么他就会形成路径依赖。

有些读书厉害的人,能迅速地绕过这个弯,这就是人杰,还有一部分人,会一直纠结在书本智慧和现实的差距里,做事总是慢半拍,等他想明白了,总是晚了一步,这就让他需要用三年、五年,甚至有些人会用十年二十年的时间,去适应游戏规则。

 

以前有个笑话:

有一个人去算命。

大师告诉他:你在40岁以前会过得很苦。 

这个人一想,还好,虽然有40年,但是毕竟人生只过去一半。 

他问:40岁以后会怎么样? 

大师说:40岁以后你就习惯了。

 

一个人,如果前半生都在适应规则,那么他很可能适应适应着,人就颓了,后半生也就不会再振作了。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

 

《大宅门》里的白二爷,是有名的懦弱没本事。

 

但是白景琦对他有个评价,「一生襟抱未曾开」。这也不全是儿子对父亲的回护,而是白二爷这个人,也是读书人,但是白二爷一生却到处被人欺负,因为他碰到的都是各种耍横的手段,各种无耻无赖的手段,甚至在家里,都不如家里最没本事最无赖的纨绔子弟白三爷吃得开。

 

同样,白大爷也是,白大爷为了给母亲尽孝,送给母亲一个礼物,是个夜壶,结果把老太太鼻子都气歪了,再拿糕点去给母亲赔罪,老太太就是不吃,但是同样是糕点,白三爷就能骗老太太吃下去。

 

为什么?

 

因为白大爷白二爷都是读书人,都是厚道人;

因为任何一本书上都不会写,「给母亲送礼物不应该送夜壶」;

因为任何一本书上都不会写,「怎么骗母亲吃糕点」。

 

书上都是圣贤道理,怎么会讲这么不入流的小事?所以,在混社会这点上,白大爷、白二爷,都不如白文氏,也就是二奶奶。

 

白二爷也知道自己不如老婆,所以白三爷撺掇他跟老婆争权,他亲口承认:我,不如娘们儿」。

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

这就是白二爷认识到自己的短板,他对付不了那些小人,二奶奶能,二奶奶那些撕逼和笼络人心的手腕、逢迎拍马的做法,就是好使,但是白二爷真的做不到,白大爷也做不到。

 

所以白大爷,白二爷在混社会这件事上,不如二奶奶,甚至连自己的弟弟,每天喝酒、打牌、逛窑子的白三爷都不如,就算到老了,白三爷还能跟打了一辈子仗的二奶奶凑一桌麻将,白二爷只会玩他的那些书画古玩,哪个女人会稀罕这些?

 

但是,是白二爷读的书不对吗?

不是。

二奶奶精明厉害,但是她也有她解决不了的问题,白景琦,所以她请了一个先生来教她儿子,就是季宗布季先生。

 

季先生也是读书人,但是季先生是什么人?季先生既是神机营的武师,也是国子监的监生,后来不教白景琦,是因为要调他任军机处章京。

 

他处理问题的手段和格局,是二奶奶所不能梦见的。

 

季宗布下场不好,最后死在八国联军手里,但是那是因为,「大丈夫做人的道理,我便跟你说了,你也不会明白。」并不是季宗布不想混好。

 

同样是读书人,季宗布和白二爷有什么区别?

 

第一个区别,是季宗布有很多白二爷不会的对付江湖伎俩和宵小的手段。

 

第二个区别,是白二爷从来都没有进入过庙堂视野,而季宗布,从来就没有远离过庙堂。

 

所以,季宗布如鱼得水,做人做事,胜似闲庭信步,都有不自觉的自信和笃定。

 

换句通俗地话说,白二爷在底层,白大爷在第二层,白三爷在第三层,二奶奶在第四层,而季先生在第五层。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

书上的道理不是没有用,而是书上的道理都是圣贤道理,庙堂手段。

 

任何一个时代的教育体系能教给你的,只能是正道,只能是圣贤道理、庙堂手段,都是高层的奥义,是至少给你做总经理,总工程师才能用上的,但是,很多人的问题是,一辈子进不了高层,一辈子进不了庙堂。

 

所以「一生襟抱未曾开」,上句是,「虚负凌云万丈才」。

聪明,也是个聪明人,才华,也是有的,但是就是迈不过这个坎儿,这就是「英雄无用武之地」。

 

 

很多读书很厉害,学历很高的人反而会在开始的时候混的不好,或者遇到很多困难,很多蠢货借此大谈读书无用论,其实不是,但是事实上,不是书本智慧不对,也不是我们的教育系统存在问题。

 

我前几年,也特别喜欢批判教育系统,谈教育系统的弊端,但是现在越来越发现,这是所有公立教育系统都存在的问题,甚至不能称之为弊端,书本上教你的很多道理全部都有用,但是这些东西在你刚进入社会的时候没有用武之地。

 

因为你的庙堂手段,圣贤道理,遇到的都是市井人群,市井手段。

 

这就是街头智慧。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

所谓的街头智慧,就是「不学有术street smart,这种智慧是完全靠生存经验积累出来的技能。有一种人,没怎么读过书,但是同样可以在社会上混的不错,这种人就是具有街头智慧的人。

 

拥有这种智慧的人,因为在人群里打拼的多了,所以自然而然就知道怎么不动声色的摆平这些事,怎么笑着摆平这些厚脸皮的人。当你还在发愁怎么拒绝别人不合理要求的时候,他已经笑着说了一句话,既给了别人面子,又顺利的把这件事情推掉了。

 

这种人在刚进入社会的时候,可能起点没有你高,但是他会比你更适应这个社会,所以反而会混得很好,这就是街头智慧的力量。

 

 

我遇到过一个人,他说他是整个单位学历最低的,但是他有一个本事,如果他让别人给他帮忙做事,没有人会不帮忙,你猜,后来上级提拔一个人,提拔的是谁?

 

 

为什么有街头智慧的人,开始会混得很好,因为他可以无缝衔接,因为你在人生一开始遇到的人、遇到的事,不需要那么大的道理,他们也不值得你用那么高深的道理去对待。

 

多数人能够看到的事,也就是上升1-2个阶层,1-2个level的事,所谓的升阶,对大多数人的一生而言,就是升一到两阶层。

 

而这时候,街头智慧比书本智慧好用。

 

换言之,你能修炼成白三爷就够用了,修炼成二奶奶就是成精了,你用不着修炼成季宗布,大多数想修炼成季宗布的人,都修炼成了白二爷。

 

所以,我们经常看到,不那么喜欢读书的人,往往混得好。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

这就是:

现实需要你服膺强者,你学的一肚子刚正不阿;

现实需要你见风使舵,你学的一肚子百折不挠。

 

所以,你以为你在别人眼里是古之士大夫,是高风亮节,是不苟于流俗,出淤泥而不染,而实际上在别人嘴里,只会嘴角轻启,轻蔑地吐出俩字,「傻X」。死读书、情商低、固执、有点轴,这都是很客气的说法了。

 

实际上,背着你,就是俩字,「傻X」

 

 

但是,不是读书没有用,而是书上的问题你遇不到,你遇到的是什么问题?

 

同事总想偷懒怎么办?

总想甩锅怎么办?

你的领导不负责任怎么办?

 

你怎么去应对这些人?这才是我们每天会切切实实遇到的,这种问题,用书本上的大道理是解决不了的,所以这时候,你真正需要的,是街头智慧。

 

你解决不了这些问题,你就没有机会突破现有的阶层。

 

这就是只有书本智慧没有街头智慧的局限。

 

实际上,等你到了更高层的阶段,你才需要坦荡光明,没有任何黑点,因为这样你才能在更高层的领域活下去,才能发展到更高级的位置。你的身世越清白,你的历史、履历越光明,你才能走的越远。

 

而且等你到了更高的层次,你需要更多的思维工具,更多的案例去解决你的困境,这时候,没有读过书的人,问题就来了。

 

 

成龙在一个采访中,被问到最羡慕李小龙哪一点?他的回答就是,羡慕李小龙读过书。

 

所有只具备街头智慧的人,当他达到一个比较高层的位置的时候,都会遭遇一种困境,就是没有办法进一步的上升了。因为他没有读过多少书,也就没有办法去理论性的看待这个世界。

像成龙他们这种龙虎武师出身的香港武打演员,基本上都没有读过什么书,很早就出来作武行、做武打替身了。而成龙能到达现在的高度,确实是很聪明,比如李小龙打法,全是那种往高踢,很帅,而且无坚不摧,几乎不怕痛,大家都喜欢,但是成龙知道自己不能跟他一样,必须要换一种打法,有自己的特色,才是长久的生存之道。

 

所以,他想办法,就是往低了踢,就是一下打到柱子,一下子痛得缩回来直摇手,一下子就接地气了,大家看李小龙,是英雄,但是看成龙,会觉得那就是自己。

 

这就是「街头智慧」,这是只有在底层摸爬滚打过的草根,才会懂的道理。

 

成龙能在电影里或者香港的演艺圈混的如鱼得水,因为他本身就是这样的江湖中人,一步步摸爬滚打上来的,所以很容易就能适应社会规则。

 

但是他到了一定阶段,到了一定的高度,想要把自己的人生经验,进行总结的时候,他发现,自己没有办法去输出,也没有办法提高了,我看成龙的采访,能看到他的难受,实际上,他有很多东西想表达出来,但是他表达不了那么精准,当然,他有他的智慧,他会有各种比喻和形象的描述来「意会」。

 

这就是只有街头智慧缺乏书本智慧的局限性。

 

 

街头智慧和书本智慧,各有各的局限,但是,只有书本智慧的窘迫,更强一些。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

真正能走到最高层的,一定是书本智慧和街头智慧兼有的人。

 

 

一个读过书、有修养,同时又能在基层玩得转的人,一定会走的很远。光有书本智慧的人开始混社会的时候,可能会发现自己跟社会格格不入,做人做事也常常被笑是书呆子、迂腐,但是这些人一旦获得了街头智慧,那么在过了最开始的阶段,要向高层上升的时候,往往就会变得如鱼得水。但是这样先有书本智慧,后有街头智慧的人,万中无一。

 

同样,能够从街头智慧逐渐发展为拥有书本智慧的人,也可以走的很远。比如历史上的刘邦,一开始就是一个混混、游侠,但是后来逐渐的开始听儒生给他讲书、讲道理,可能在听完之后,他自己的文化水平还是没有提高,但是他在做事的过程中可以逐渐的积累书本智慧,所以他能成为一个帝国的开创者。同样,朱元璋也是,从开始一个目不识丁的人,到最后能写诗、写文章,能自己独立的处理各种政事,也是完成了街头智慧向书本智慧的提升。

 

有句诗,坑灰未冷山东乱,刘项原来不读书。

 

佐竹靖彦有本书叫《刘邦》,他认为秦末天下大乱,各路义军的实力派,几乎都是各地的游侠,其中以淮泗的游侠最为活跃,刘邦为什么能够成为特殊的一个,就是因为,刘邦相比起其他游侠,开始突破自己旧有格局的限制,开始读书,开始任用有文化的知识分子。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

 

 

有一本书叫《街角社会》,作者观察的对象就是美国意大利裔的街头黑帮,他发现一个现象,能够在这些小混混中脱颖而出,成为大混混的人,都是能够服众,敢打敢拼讲义气,具有鲜明的草根烙印,有底层街头智慧的人。

其中一个帮会诺顿帮,领导者多克是一个具有个人魅力的混混头目,诺顿帮实行的是有福同享有难同当的模式,多克平常通过花钱大方,被「兄弟们」支持,但是他有机会参加政治选举,却苦于囊中羞涩没有经济来源,放弃了上层流动的机会。

 

这些处于社会的街角青年能够看到改变自己底层生存状态的机会,却永远实现不了这个愿望,因为他们在少年时代就习惯了街头的行为方式,没有为实现社会流动而作任何的努力与准备,当机会来临,他们的口袋和脑袋都空空如也。

 

 

这正是「古惑仔没脑子,一辈子都是古惑仔」。

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

不过,其中,却有一些有远见的混混头目,凭借自己众多的人脉,支持一名议员当选,来谋求更大的利益;或者努力凭借实力开展合法商业活动,借此「洗白,步入上流社会,甚至挤入政治家行列。

 

但是,同样是街角社会,还有一批意大利裔大学生,他们组建俱乐部,关注社会问题。这些目标远大,受过高等教育的大学生们,雄心勃勃,但是他们的俱乐部跟黑帮相比,却没有任何生命力,他们组织的成员,在自己社会地位有所改善之后,就会迅速离开组织,而他们之间的关系非常松散也容易破裂。

 

当地的政治家,也几乎不重视这些大学生团体,因为他们几乎没有任何情感纽带。

 

这正是应了一句话,「仗义每多屠狗辈,负心多是读书人」。

 

 

 

认真聊聊:读书很厉害的人,为什么会混得不好?

 

 

 

在底层的时候,街头智慧很重要,如果你没有,那么很多事情都处理不了,或者你只能成为一个普通的技术性的工具人。

 

但是当你进入中层之后,书本智慧就开始变得越来越重要,你所讲的那些原则就会越来越重要,为什么过去的很多武将,到一定阶段就一定要读书?因为不读书已经不行了,不读书已经不足以解决他遇到的问题了。

 

同样,读过书,拥有书本智慧的人,也要去经历事情,去学会跟基层的人打交道。如果你一开始就在一个很高层的位置上,缺乏基层的生存和处事经验,也不去跟下面的人接触,那么你是可能在开始的时候拿高薪,但是你也只能成为一个「高蹈派,只能漂浮在上,成为一个悬空人。你没有办法接触底层的运营逻辑,因为缺乏领导力,没有办法去统帅那些能力不如你的人,也就无法组建自己的班底。所以,你想独立的领导一个团队是不可能的,因为你碰到的都是你无法摆平的人。

 

最近读史书,发现世界上能混得好的有两种人,一种人是先获得街头智慧,然后肯读书获得书本智慧的人,中国的史书,把这叫做「折节向学」

 

第二种人,是先有书本智慧,还能够去做实事,积累街头智慧,这就是「把手弄脏」,读书很厉害的人,怎么都会有向上的路,最忌的是隔岸观火,像白二爷一样,自己去沉迷于「小道」,去自我安慰糊弄自己,彻底出不来了,最重要的是「把手弄脏」。

 

换句话说:

古惑仔要读书、要有脑;

书生要实干,反而不要太计较得失,反而要无脑。

 

只有把这两种智慧相结合,既能处理下面的问题,又能带领团队提升,这样的人才是真正能混好的人,在任何一个社会,都是这样的逻辑。

 

 

参考文献:

1. 《刘邦》 佐竹靖彦

2. 《街角社会》  威廉·富特·怀特

3. 《街头智慧:罗杰斯的投资与人生》 吉姆·罗杰斯

END

转自:https://mp.weixin.qq.com/s/7OoKaFs9o3SnEVFqx-0CGQ

直播带货,借刀杀人

对面菜市场里,王婶是天天在辛巴直播间买东西的人。她的快递一到,所有菜贩子便都看着他笑,有的叫道,“王婶,你又添了没用的物件了吧?”她不作声,打开手机,进入直播间送了几个啤酒。他们又故意的高声嚷道,“你一定借小贷打的赏吧!”王婶睁大眼睛说,“你怎么这样凭空污人清白……”“什么清白?我前天亲眼见你接了催收电话的。”王婶便涨红了脸,额上的青筋条条绽出,争辩道,“打赏还能算借……打赏!……给爱豆花钱,能算借么?”接连便是难懂的话,什么“用爱发电,什么“认知”之类,引得众人都哄笑起来,菜市场内充满了快活的空气。

 

正是千千万万个王婶,撑起了辛巴日进斗金的直播间,也撑起了淘宝流量花园里的两棵参天大树:一棵是薇娅,一棵是李佳琦。如今,薇娅这棵大树都倒下了,我才发现还没聊过直播带货这事——旬月之间养成的大主播,收入居然远超传统的流量明星!这让我们这些吃瓜群众,刷空了钱包后陷入沉思:直播带货,为什么能平地抠饼地聚敛起这么多财富呢?

 

来,我们直指人心,见性成佛。其实,直播带货的本质很简单——这是平台在借刀杀人。这里的逻辑说起来稍微有点话长,您慢慢往下看。

 

互联网挣钱的基本逻辑

互联网平台的变现手段有哪些呢?看起来能说出一大串:广告、游戏、电商、金融……但是我们抛开表象,直击本质的话,会发现支撑这些五花八门变现手段的核心资产,可以归结到两项:流量和数据。

 

有流量,就能在用户来访时,夹带私货放广告挣钱;有数据,就能给不同人群的流量匹配合适的广告,提升挣钱的效率。于是,广告成了互联网公司流量和数据变现的最普适形式。其中的基本逻辑,我们的视频号@北冥乘海生 讲过很多次了。不熟悉的朋友可以简单看看下图,这里不再赘述。

直播带货,借刀杀人

而那些自己下场做电商的、做游戏的、放贷的,其实不过是把广告商的大力丸扔在一边,自产自销大力丸罢了。而他们所擅长的,也并不是研发大力丸,而是用流量和数据把它卖出去。

 

有人说,我知道一些没流量也没数据的游戏公司,也赚的盆盈钵满啊?当然,你研发大力丸本事过硬,也能分一杯羹。可是手里有流量数据的平台,那是插根扁担都开花,不用天天琢磨大力丸的工艺创新。不信,我问你个问题:为什么游戏公司的市盈率基本在4-8倍,而腾讯的市盈率是几十倍呢?

 

所以,在互联网平台看来,管你谁有创意、谁有技术,不在老子这儿交买路钱,一个子儿也甭想挣!

 

然而,依靠流量和数据卖广告也好,亲自下场卖大力丸也罢,会遇到增长的天花板。某大厂的一次调研发现,随着年龄下降,广告点击率显著下降:越年轻的群体互联网原住民越多,早就熟悉了这套夹私货的手段,渐渐也就免疫了。

 

别急,这就要说到直播带货了!

 

新的摇钱树——影响力网络

流量和数据变现遇上天花板,可是东方不亮西方亮,互联网社交化以后,平台又多了一项重要资产。这项资产,我把它叫做“影响力网络”。

 

什么是影响力网络呢?在社交化平台上,用户除了接收信息,还可以输出内容和情绪。如果某人的粉丝很多,粘性又强,那么他就建立了自己的影响力资产。众多的大V网红环环相扣,就织成了一张影响力组织起来的天罗地网。

直播带货,借刀杀人

好,这里有两个常见的疑问。

第一个疑问:影响力资产不是属于大V么,为啥说是平台的资产?表面上看,你的粉丝归你所有,有人把这个叫私域。可是你想想:如果平台的算法不让你的粉丝都看到你的内容,你有辙么?所以啊,千万别拿村长不当干部,大V你再牛逼,还是跳不出平台的手掌心。于是,你积累那点私域资产,迟早还得帮平台挣钱。

 

     第二个疑问:影响力跟流量和数据,本质上是一回事么?还真不是。给大家举个例子,我认识一个大V,他做实验找了一款滞销的T恤,自己穿上写了一大段吹捧的词儿,居然价量都翻了番,远超直接在平台推广告的效果。

 

     平台用广告推产品,靠的是流量和数据;大V向自己的粉丝推产品,转化率高出来的部分,就是影响力资产变现的价值。说白了,由于粉丝对自己的偶像感知到了温度,产生了盲从,对其推广的内容信任程度,远高于平台出面搞得那性冷淡的广告位。没错,影响力资产的关键价值,就是粉丝的盲从。

 

     辛巴和薇娅的直播间里,就是因为有无数个盲从的王婶,才种上了摇钱树。对他们来说,辛巴和薇娅,那就是神啊!

 

有的读者可能会有疑问:如果平台直接出面宣传自己的神性,培养粉丝的盲从,能不能达到一样的效果呢?

问题在于,平台只能以单一的形象和调性示人:你不能又是知识范儿,又是二次元,就像我不能雌雄同体一样。于是,只有对平台调性感冒的那一小撮人,才有可能盲从,这哪儿够!

让大V出面,这事就简单了:管你喜欢洋的土的、瘪的鼓的、跳艳舞的、还是唱大鼓的,平台上千千万万的大V,总有一款适合你!

说到这儿,您应该明白,为什么毗湿奴神有十大化身,而印度教各路神仙有十万之众了吧?这些一抬脚踩死一片的大神,就是元宇宙里等着收割你的大V们啊!

 

借刀杀人的变现方式

     于是,形成了庞大影响力网络的平台,酝酿出了崭新的变现手段:让大V在前面卖大力丸,让他盲从的粉丝们疯狂买单,平台躲在后面分成收割就好了。具体的产品逻辑是这样的:

  1.   首先,为平台赋予社交媒体属性,帮助有鲜明内容特色或人格特质的博主聚敛粉丝;

  2.  然后,为这些大V博主提供变现手段,最直接的就是直播带货,让他们利用自己粉丝的盲从,疯狂地对韭当割;

  3. 平台收税的手段,是暗自收紧流量口子,让大V不能顺畅触达自己的粉丝。在带货的同时,必须拿出大头投广告,才能获得流量。

 

     这里面关键而隐秘的,是上面的第3点。所以,今天商业化成功的平台,都靠算法分发而非社交关系来分配流量。我知道一位八位数粉丝的大V小Y,头回直播带货以为拥趸众多,根本没投广告,结果呢?整场下来才27万销售额!

 

     而另外一个大V小X,粉丝远没有小Y多,可是每次直播带货销售额稳定在两百多万。只不过——其中一半多都要拿出来投广告,作为给平台的供品。

 

直播带货,借刀杀人

     这种影响力网络形成的利益收割与输送关系,可以用上图中可爱的象头神伽内什来类比:在印度教中,伽内什是重要的首祭之神,凡人的供品都是上给他的,然而他过一道手,还得交给他爸爸湿婆大神。在直播带货这个生态中,大V就是伽内什,粉丝就是他的信众,而平台才是背后的湿婆大神。

 

所以,大V们别以为你手里有粉丝,就可以在平台面前呼风唤雨了!你们推到前台收供品的镰刀,割完了韭菜该交给谁,心里得有点数!

您可能要说,既然是粉丝多的就能成为V,那这就是群众意志的反应啊!这难道不能去芜存菁,把那些只是割韭菜的大V淘汰掉么?

 

这么想,你真的小看平台逐利的本事了:表面上看起来,互联网的信息是开放而自由的,可是利用数据和算法上下其手,最后成长起来的大V,一定是符合平台目标函数的那批——一般来说,也就是煽动性最强,镰刀磨得最快的那一批。关于这一点的详细分析解说,大家可以参见下面的视频。

@-@

最后,再看说说李佳琦薇娅头部主播,他们直播间里卖的东西倒还不全是割韭菜,确实有很多价廉物美的。这是怎么回事呢?他们在形成了影响力网络里只手遮天的大结点之后,形成了反向收割客户的能力——谁要想在他们这儿宣传产品,对不起,你先得给我个好的折扣。毕竟,在今天这二位对品牌的推广力度,比央视可有效多了。

另外,我们如果对比抖音和淘宝的直播生态的话,会发现前者的影响力网络结构,远不是像后者那样集中在两棵大树上。那么,哪种生态对平台的收益更加有利呢?如果对我们前面的一些文章保持关注的话,那么结论是明摆着的:显然是抖音的策略对平台更有利。

那么,为什么淘宝会形成这种两个大树的畸形生态呢?这恐怕要从内部找原因了。不管怎么说,现在倒下了大树,对淘宝应该是个大利好。毕竟一鲸落,才能万物生。

作为一颗茁壮成长的韭菜,我们当然无法收割平台借刀杀人的强大收割机器,只是在面对明晃晃的镰刀时,不要把它当成的神灵头上的光环,迷瞎了自己的双眼。


转自:https://mp.weixin.qq.com/s/p80kMTo0Ie8KmtUGAuquNQ