8000 GitHub - Ss-shuang123/interview: 📚 C/C++ 技术é¢è¯•基础知识总结,包括语言ã€ç¨‹åºåº“ã€æ•°æ®ç»“æž„ã€ç®—法ã€ç³»ç»Ÿã€ç½‘络ã€é“¾æŽ¥è£…载库等知识åŠé¢è¯•ç»éªŒã€æ‹›è˜ã€å†…推等信æ¯ã€‚This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, e
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
8000 forked from huihut/interview

📚 C/C++ 技术é¢è¯•基础知识总结,包括语言ã€ç¨‹åºåº“ã€æ•°æ®ç»“æž„ã€ç®—法ã€ç³»ç»Ÿã€ç½‘络ã€é“¾æŽ¥è£…载库等知识åŠé¢è¯•ç»éªŒã€æ‹›è˜ã€å†…推等信æ¯ã€‚This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, e

License

Notifications You must be signed in to change notification settings

Ss-shuang123/interview

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

📖 Github    |    📚 Docsify

简体中文    |    English

💡 关于

📚 本仓库是é¢å‘ C/C++ æŠ€æœ¯æ–¹å‘æ ¡æ‹›æ±‚èŒè€…ã€åˆå­¦è€…的基础知识总结,包括语言ã€ç¨‹åºåº“ã€æ•°æ®ç»“æž„ã€ç®—法ã€ç³»ç»Ÿã€ç½‘络ã€é“¾æŽ¥è£…载库等知识åŠé¢è¯•ç»éªŒã€æ‹›è˜ã€å†…推等信æ¯ã€‚

💡 ä¾§è¾¹ç›®å½•æ”¯æŒæ–¹å¼ï¼šðŸ“š Docsify 文档ã€Github + TOC 导航(TOC预览.png)

📄 ä¿å­˜ä¸º PDF æ–¹å¼ï¼šä½¿ç”¨ Chrome æµè§ˆå™¨æ‰“å¼€ 📚 Docsify 文档 页é¢ï¼Œç¼©èµ·å·¦ä¾§ç›®å½•-å³é”® - æ‰“å° - é€‰æ‹©ç›®æ ‡æ‰“å°æœºæ˜¯å¦å­˜ä¸ºPDF - ä¿å­˜ï¼ˆæ‰“å°é¢„览.png)

🙠仓库内容如有错误或改进欢迎 issue 或 pr,建议或讨论å¯åœ¨ #12 æå‡ºã€‚由于本人水平有é™ï¼Œä»“库中的知识点有æ¥è‡ªæœ¬äººåŽŸåˆ›ã€è¯»ä¹¦ç¬”è®°ã€ä¹¦ç±ã€åšæ–‡ç­‰ï¼ŒéžåŽŸåˆ›å‡å·²æ ‡æ˜Žå‡ºå¤„ï¼Œå¦‚æœ‰é—æ¼ï¼Œè¯· issue æå‡ºã€‚本仓库éµå¾ª CC BY-NC-SA 4.0(署å - éžå•†ä¸šæ€§ä½¿ç”¨ - ç›¸åŒæ–¹å¼å…±äº«ï¼‰ å议,转载请注明出处,ä¸å¾—用于商业目的。

📑 目录

âž• C/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 åŽé¢ï¼‰çš„值ä¸å¯æ”¹å˜ï¼Œå¦‚下文使用例å­ä¸­çš„ p2ã€p3

使用

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 常é‡

å®å®šä¹‰ #define const 常é‡
å®å®šä¹‰ï¼Œç›¸å½“äºŽå­—ç¬¦æ›¿æ¢ å¸¸é‡å£°æ˜Ž
预处ç†å™¨å¤„ç† ç¼–è¯‘å™¨å¤„ç†
无类型安全检查 有类型安全检查
ä¸åˆ†é…内存 è¦åˆ†é…内存
å­˜å‚¨åœ¨ä»£ç æ®µ å­˜å‚¨åœ¨æ•°æ®æ®µ
å¯é€šè¿‡ #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 (如åªè¯»çš„çŠ B93C ¶æ€å¯„存器)
  • 指针å¯ä»¥æ˜¯ 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 __cplusplus
extern "C" {
#endif

void *memset(void *, int, size_t);

#ifdef __cplusplus
}
#endif

struct 和 typedef struct

C 中

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

等价于

// c
struct Student { 
    int age; 
};

typedef struct Student S;

此时 S 等价于 struct Student,但两个标识符å称空间ä¸ç›¸åŒã€‚

å¦å¤–还å¯ä»¥å®šä¹‰ä¸Ž struct Student ä¸å†²çªçš„ void Student() {}。

C++ 中

由于编译器定ä½ç¬¦å·çš„规则(æœç´¢è§„则)改å˜ï¼Œå¯¼è‡´ä¸åŒäºŽC语言。

一ã€å¦‚果在类标识符空间定义了 struct Student {...};,使用 Student me; 时,编译器将æœç´¢å…¨å±€æ ‡è¯†ç¬¦è¡¨ï¼ŒStudent 未找到,则在类标识符内æœç´¢ã€‚

å³è¡¨çŽ°ä¸ºå¯ä»¥ä½¿ç”¨ Student 也å¯ä»¥ä½¿ç”¨ struct Student,如下:

// cpp
struct 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;         // 全局(::)的 count

class 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 };

decltyp F438 e

decltype 关键字用于检查实体的声明类型或表达å¼çš„类型åŠå€¼åˆ†ç±»ã€‚语法:

decltype ( expression )

decltype 使用

// 尾置返回å…è®¸æˆ‘ä»¬åœ¨å‚æ•°åˆ—表之åŽå£°æ˜Žè¿”回类型
template <typename It>
auto fcn(It beg, It end) -> decltype(*beg)
{
    // 处ç†åºåˆ—
    return *beg;    // 返回åºåˆ—中一个元素的引用
}
// 为了使用模æ¿å‚æ•°æˆå‘˜ï¼Œå¿…须用 typename
template <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) type
new (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)概念。多个智能指针指å‘相åŒå¯¹è±¡ï¼Œè¯ 10000 ¥å¯¹è±¡å’Œå…¶ç›¸å…³èµ„æºä¼šåœ¨ “最åŽä¸€ä¸ª 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. å®å¯ä»¥ç¼–译器替æ¢é¢„处ç†å™¨ï¼ˆå°½é‡ä»¥ constã€enumã€inline æ›¿æ¢ #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)expressionã€T(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_castã€const_castã€dynamic_castã€reinterpret_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 operatorã€operator newã€placement newã€operator new[]ï¼›delete operatorã€operator deleteã€destructorã€operator 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(超急评估)å¯ä»¥æ”¹å–„ç¨‹åºæ•ˆçŽ‡ï¼‰

Google C++ Style Guide

å…¶ä»–

📦 STL

STL 索引

STL 方法å«ä¹‰ç´¢å¼•

STL 容器

容器 底层数æ®ç»“æž„ æ—¶é—´å¤æ‚度 æœ‰æ— åº å¯ä¸å¯é‡å¤ å…¶ä»–
array 数组 éšæœºè¯»æ”¹ O(1) æ— åº å¯é‡å¤ 支æŒéšæœºè®¿é—®
vector 数组 éšæœºè¯»æ”¹ã€å°¾éƒ¨æ’å…¥ã€å°¾éƒ¨åˆ é™¤ O(1)
头部æ’å…¥ã€å¤´éƒ¨åˆ é™¤ O(n)
æ— åº å¯é‡å¤ 支æŒéšæœºè®¿é—®
deque åŒç«¯é˜Ÿåˆ— 头尾æ’å…¥ã€å¤´å°¾åˆ é™¤ O(1) æ— åº å¯é‡å¤ 一个中央控制器 + 多个缓冲区,支æŒé¦–尾快速增删,支æŒéšæœºè®¿é—®
forward_list å•å‘链表 æ’å…¥ã€åˆ é™¤ O(1) æ— åº å¯é‡å¤ 䏿”¯æŒéšæœºè®¿é—®
list åŒå‘链表 æ’å…¥ã€åˆ é™¤ O(1) æ— åº å¯é‡å¤ 䏿”¯æŒéšæœºè®¿é—®
stack deque / list 顶部æ’å…¥ã€é¡¶éƒ¨åˆ é™¤ O(1) æ— åº å¯é‡å¤ deque 或 list å°é—­å¤´ç«¯å¼€å£ï¼Œä¸ç”¨ vector 的原因应该是容é‡å¤§å°æœ‰é™åˆ¶ï¼Œæ‰©å®¹è€—æ—¶
queue deque / list 尾部æ’å…¥ã€å¤´éƒ¨åˆ é™¤ O(1) æ— åº å¯é‡å¤ deque 或 list å°é—­å¤´ç«¯å¼€å£ï¼Œä¸ç”¨ vector 的原因应该是容é‡å¤§å°æœ‰é™åˆ¶ï¼Œæ‰©å®¹è€—æ—¶
priority_queue vector + max-heap æ’å…¥ã€åˆ é™¤ O(log2n) æœ‰åº å¯é‡å¤ vector容器+heap处ç†è§„则
set 红黑树 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(log2n) æœ‰åº ä¸å¯é‡å¤
multiset 红黑树 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(log2n) æœ‰åº å¯é‡å¤
map 红黑树 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(log2n) æœ‰åº ä¸å¯é‡å¤
multimap 红黑树 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(log2n) æœ‰åº å¯é‡å¤
unordered_set 哈希表 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(1) 最差 O(n) æ— åº ä¸å¯é‡å¤
unordered_multiset 哈希表 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(1) 最差 O(n) æ— åº å¯é‡å¤
unordered_map 哈希表 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(1) 最差 O(n) æ— åº ä¸å¯é‡å¤
unordered_multimap 哈希表 æ’å…¥ã€åˆ é™¤ã€æŸ¥æ‰¾ O(1) 最差 O(n) æ— åº å¯é‡å¤

STL 算法

算法 底层算法 æ—¶é—´å¤æ‚度 å¯ä¸å¯é‡å¤
find é¡ºåºæŸ¥æ‰¾ O(n) å¯é‡å¤
sort å†…çœæŽ’åº O(n*log2n) å¯é‡å¤

ã€½ï¸ æ•°æ®ç»“æž„

顺åºç»“æž„

é¡ºåºæ ˆï¼ˆSequence Stack)

SqStack.cpp

é¡ºåºæ ˆæ•°æ®ç»“构和图片

typedef struct {
	ElemType *elem;
	int top;
	int size;
	int increment;
} SqStack;

队列(Sequence Queue)

队列数æ®ç»“æž„

typedef struct {
	ElemType * elem;
	int front;
	int rear;
	int maxSize;
}SqQueue;
éžå¾ªçŽ¯é˜Ÿåˆ—

éžå¾ªçŽ¯é˜Ÿåˆ—å›¾ç‰‡

SqQueue.rear++

循环队列

循环队列图片

SqQueue.rear = (SqQueue.rear + 1) % SqQueue.maxSize

顺åºè¡¨ï¼ˆSequence List)

SqList.cpp

顺åºè¡¨æ•°æ®ç»“构和图片

typedef struct {
	ElemType *elem;
	int length;
	int size;
	int increment;
} SqList;

链å¼ç»“æž„

LinkList.cpp

LinkList_with_head.cpp

链弿•°æ®ç»“æž„

typedef struct LNode {
    ElemType data;
    struct LNode *next;
} LNode, *LinkList; 

链队列(Link Queue)

链队列图片

线性表的链å¼è¡¨ç¤º

å•链表(Link List)

å•链表图片

åŒå‘链表(Du-Link-List)

åŒå‘链表图片

循环链表(Cir-Link-List)

循环链表图片

哈希表

HashTable.cpp

概念

哈希函数:H(key): K -> D , key ∈ K

构造方法

  • ç›´æŽ¥å®šå€æ³•
  • 除留余数法
  • æ•°å­—åˆ†æžæ³•
  • æŠ˜å æ³•
  • 平方å–中法

冲çªå¤„ç†æ–¹æ³•

  • é“¾åœ°å€æ³•:key 相åŒçš„用å•链表链接
  • å¼€æ”¾å®šå€æ³•
    • 线性探测法:key ç›¸åŒ -> 放到 key 的下一个ä½ç½®ï¼ŒHi = (H(key) + i) % m
    • 二次探测法:key ç›¸åŒ -> 放到 Di = 1^2, -1^2, ..., ±(k)^2,(k<=m/2)
    • éšæœºæŽ¢æµ‹æ³•:H = (H(key) + ä¼ªéšæœºæ•°) % m

线性探测的哈希表数æ®ç»“æž„

线性探测的哈希表数æ®ç»“构和图片

typedef char KeyType;

typedef struct {
	KeyType key;
}RcdType;

typedef struct {
	RcdType *rcd;
	int size;
	int count;
	bool *tag;
}HashTable;

递归

概念

函数直接或间接地调用自身

递归与分治

  • 分治法
    • 问题的分解
    • 问题规模的分解
  • æŠ˜åŠæŸ¥æ‰¾ï¼ˆé€’归)
  • 归并排åºï¼ˆé€’归)
  • 快速排åºï¼ˆé€’归)

递归与迭代

  • 迭代:åå¤åˆ©ç”¨å˜é‡æ—§å€¼æŽ¨å‡ºæ–°å€¼
  • æŠ˜åŠæŸ¥æ‰¾ï¼ˆè¿­ä»£ï¼‰
  • 归并排åºï¼ˆè¿­ä»£ï¼‰

广义表

头尾链表存储表示

广义表的头尾链表存储表示和图片

// 广义表的头尾链表存储表示
typedef enum {ATOM, LIST} ElemTag;
// ATOM==0:原å­ï¼ŒLIST==1:å­è¡¨
typedef struct GLNode {
    ElemTag tag;
    // 公共部分,用于区分原å­ç»“点和表结点
    union {
        // 原å­ç»“点和表结点的è”åˆéƒ¨åˆ†
        AtomType atom;
        // atom 是原å­ç»“点的值域,AtomType 由用户定义
        struct {
            struct GLNode *hp, *tp;
        } ptr;
        // ptr 是表结点的指针域,prt.hp å’Œ ptr.tp 分别指å‘表头和表尾
    } a;
} *GList, GLNode;

扩展线性链表存储表示

扩展线性链表存储表示和图片

// 广义表的扩展线性链表存储表示
typedef enum {ATOM, LIST} ElemTag;
// ATOM==0:原å­ï¼ŒLIST==1:å­è¡¨
typedef struct GLNode1 {
    ElemTag tag;
    // 公共部分,用于区分原å­ç»“点和表结点
    union {
        // 原å­ç»“点和表结点的è”åˆéƒ¨åˆ†
        AtomType atom; // 原å­ç»“点的值域
        struct GLNode1 *hp; // 表结点的表头指针
    } a;
    struct GLNode1 *tp;
    // 相当于线性链表的 next,指å‘下一个元素结点
} *GList1, GLNode1;

äºŒå‰æ ‘

BinaryTree.cpp

性质

  1. éžç©ºäºŒå‰æ ‘第 i 层最多 2(i-1) 个结点 (i >= 1)
  2. 深度为 k çš„äºŒå‰æ ‘最多 2k - 1 个结点 (k >= 1)
  3. 度为 0 的结点数为 n0,度为 2 的结点数为 n2,则 n0 = n2 + 1
  4. 有 n ä¸ªç»“ç‚¹çš„å®Œå…¨äºŒå‰æ ‘深度 k = ⌊ log2(n) ⌋ + 1
  5. å¯¹äºŽå« n ä¸ªç»“ç‚¹çš„å®Œå…¨äºŒå‰æ ‘中编å·ä¸º i (1 <= i <= n) 的结点
    1. è‹¥ i = 1,为根,å¦åˆ™åŒäº²ä¸º ⌊ i / 2 ⌋
    2. è‹¥ 2i > n,则 i 结点没有左孩å­ï¼Œå¦åˆ™å­©å­ç¼–å·ä¸º 2i
    3. è‹¥ 2i + 1 > n,则 i 结点没有å³å­©å­ï¼Œå¦åˆ™å­©å­ç¼–å·ä¸º 2i + 1

存储结构

äºŒå‰æ ‘æ•°æ®ç»“æž„

typedef struct BiTNode
{
    TElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
顺åºå­˜å‚¨

äºŒå‰æ ‘顺åºå­˜å‚¨å›¾ç‰‡

链å¼å­˜å‚¨

äºŒå‰æ ‘链å¼å­˜å‚¨å›¾ç‰‡

é历方å¼

  • å…ˆåºé历
  • 中åºé历
  • åŽç»­é历
  • 层次é历

分类

  • æ»¡äºŒå‰æ ‘
  • å®Œå…¨äºŒå‰æ ‘(堆)
    • 大顶堆:根 >= å·¦ && æ ¹ >= å³
    • å°é¡¶å †ï¼šæ ¹ <= å·¦ && æ ¹ <= å³
  • äºŒå‰æŸ¥æ‰¾æ ‘ï¼ˆäºŒå‰æŽ’åºæ ‘):左 < æ ¹ < å³
  • å¹³è¡¡äºŒå‰æ ‘(AVL树):| 左孿 ‘树高 - å³å­æ ‘树高 | <= 1
  • 最å°å¤±è¡¡æ ‘ï¼šå¹³è¡¡äºŒå‰æ ‘æ’å…¥æ–°ç»“ç‚¹å¯¼è‡´å¤±è¡¡çš„å­æ ‘:调整:
    • LL型:根的左孩å­å³æ—‹
    • RR型:根的å³å­©å­å·¦æ—‹
    • LR型:根的左孩å­å·¦æ—‹ï¼Œå†å³æ—‹
    • RL型:å³å­©å­çš„左孿 ‘ï¼Œå…ˆå³æ—‹ï¼Œå†å·¦æ—‹

å…¶ä»–æ ‘åŠæ£®æž—

树的存储结构

  • åŒäº²è¡¨ç¤ºæ³•
  • åŒäº²å­©å­è¡¨ç¤ºæ³•
  • å­©å­å…„弟表示法

并查集

一ç§ä¸ç›¸äº¤çš„å­é›†æ‰€æž„æˆçš„é›†åˆ S = {S1, S2, ..., Sn}

å¹³è¡¡äºŒå‰æ ‘(AVL树)

性质
  • | 左孿 ‘树高 - å³å­æ ‘树高 | <= 1
  • å¹³è¡¡äºŒå‰æ ‘å¿…å®šæ˜¯äºŒå‰æœç´¢æ ‘,å之则ä¸ä¸€å®š
  • 最å°äºŒå‰å¹³è¡¡æ ‘的节点的公å¼ï¼šF(n)=F(n-1)+F(n-2)+1 (1 是根节点,F(n-1) æ˜¯å·¦å­æ ‘的节点数é‡ï¼ŒF(n-2) 是å³å­æ ‘的节点数é‡ï¼‰

å¹³è¡¡äºŒå‰æ ‘图片

最å°å¤±è¡¡æ ‘

å¹³è¡¡äºŒå‰æ ‘æ’å…¥æ–°ç»“ç‚¹å¯¼è‡´å¤±è¡¡çš„å­æ ‘

调整:

  • LL 型:根的左孩å­å³æ—‹
  • RR 型:根的å³å­©å­å·¦æ—‹
  • LR 型:根的左孩å­å·¦æ—‹ï¼Œå†å³æ—‹
  • RL 型:å³å­©å­çš„左孿 ‘ï¼Œå…ˆå³æ—‹ï¼Œå†å·¦æ—‹

红黑树

RedBlackTree.cpp

çº¢é»‘æ ‘çš„ç‰¹å¾æ˜¯ä»€ä¹ˆï¼Ÿ
  1. 节点是红色或黑色。
  2. 根是黑色。
  3. 所有å¶å­éƒ½æ˜¯é»‘色(å¶å­æ˜¯ NIL 节点)。
  4. æ¯ä¸ªçº¢è‰²èŠ‚ç‚¹å¿…é¡»æœ‰ä¸¤ä¸ªé»‘è‰²çš„å­èŠ‚ç‚¹ã€‚ï¼ˆä»Žæ¯ä¸ªå¶å­åˆ°æ ¹çš„æ‰€æœ‰è·¯å¾„上ä¸èƒ½æœ‰ä¸¤ä¸ªè¿žç»­çš„红色节点。)(新增节点的父节点必须相åŒï¼‰
  5. 从任一节点到其æ¯ä¸ªå¶å­çš„æ‰€æœ‰ç®€å•路径都包å«ç›¸åŒæ•°ç›®çš„黑色节点。(新增节点必须为红)
调整
  1. å˜è‰²
  2. 左旋
  3. 峿—‹
应用
  • å…³è”æ•°ç»„:如 STL 中的 mapã€set
红黑树ã€B æ ‘ã€B+ 树的区别?
  • 红黑树的深度比较大,而 B æ ‘å’Œ B+ 树的深度则相对è¦å°ä¸€äº›
  • B+ 树则将数æ®éƒ½ä¿å­˜åœ¨å¶å­èŠ‚ç‚¹ï¼ŒåŒæ—¶é€šè¿‡é“¾è¡¨çš„å½¢å¼å°†ä»–们连接在一起。

B 树(B-tree)ã€B+ 树(B+-tree)

B æ ‘ã€B+ 树图片

B 树(B-tree)ã€B+ 树(B+-tree)

特点
  • ä¸€èˆ¬åŒ–çš„äºŒå‰æŸ¥æ‰¾æ ‘(binary search tree)
  • “矮胖â€ï¼Œå†…部(éžå¶å­ï¼‰èŠ‚ç‚¹å¯ä»¥æ‹¥æœ‰å¯å˜æ•°é‡çš„å­èŠ‚ç‚¹ï¼ˆæ•°é‡èŒƒå›´é¢„先定义好)
应用
  • å¤§éƒ¨åˆ†æ–‡ä»¶ç³»ç»Ÿã€æ•°æ®åº“系统都采用Bæ ‘ã€B+树作为索引结构
区别
  • B+æ ‘ä¸­åªæœ‰å¶å­èŠ‚ç‚¹ä¼šå¸¦æœ‰æŒ‡å‘记录的指针(ROWID),而B树则所有节点都带有,在内部节点出现的索引项ä¸ä¼šå†å‡ºçŽ°åœ¨å¶å­èŠ‚ç‚¹ä¸­ã€‚
  • B+树中所有å¶å­èŠ‚ç‚¹éƒ½æ˜¯é€šè¿‡æŒ‡é’ˆè¿žæŽ¥åœ¨ä¸€èµ·ï¼Œè€ŒBæ ‘ä¸ä¼šã€‚
B树的优点

对于在内部节点的数æ®ï¼Œå¯ç›´æŽ¥å¾—到,ä¸å¿…æ ¹æ®å¶å­èŠ‚ç‚¹æ¥å®šä½ã€‚

B+树的优点
  • éžå¶å­èŠ‚ç‚¹ä¸ä¼šå¸¦ä¸Š ROWID,这样,一个å—中å¯ä»¥å®¹çº³æ›´å¤šçš„索引项,一是å¯ä»¥é™ä½Žæ ‘的高度。二是一个内部节点å¯ä»¥å®šä½æ›´å¤šçš„å¶å­èŠ‚ç‚¹ã€‚
  • å¶å­èŠ‚ç‚¹ä¹‹é—´é€šè¿‡æŒ‡é’ˆæ¥è¿žæŽ¥ï¼ŒèŒƒå›´æ‰«æå°†å分简å•,而对于Bæ ‘æ¥è¯´ï¼Œåˆ™éœ€è¦åœ¨å¶å­èŠ‚ç‚¹å’Œå†…éƒ¨èŠ‚ç‚¹ä¸åœçš„往返移动。

B æ ‘ã€B+ 树区别æ¥è‡ªï¼šdifferences-between-b-trees-and-b-treesã€Bæ ‘å’ŒB+树的区别

八剿 ‘

八剿 ‘图片

八剿 ‘(octree),或称八元树,是一ç§ç”¨äºŽæè¿°ä¸‰ç»´ç©ºé—´ï¼ˆåˆ’分空间)的树状数æ®ç»“æž„ã€‚å…«å‰æ ‘çš„æ¯ä¸ªèŠ‚ç‚¹è¡¨ç¤ºä¸€ä¸ªæ­£æ–¹ä½“çš„ä½“ç§¯å…ƒç´ ï¼Œæ¯ä¸ªèŠ‚ç‚¹æœ‰å…«ä¸ªå­èŠ‚ç‚¹ï¼Œè¿™å…«ä¸ªå­èŠ‚ç‚¹æ‰€è¡¨ç¤ºçš„ä½“ç§¯å…ƒç´ åŠ åœ¨ä¸€èµ·å°±ç­‰äºŽçˆ¶èŠ‚ç‚¹çš„ä½“ç§¯ã€‚ä¸€èˆ¬ä¸­å¿ƒç‚¹ä½œä¸ºèŠ‚ç‚¹çš„åˆ†å‰ä¸­å¿ƒã€‚

用途
  • 三维计算机图形
  • 最邻近æœç´¢

âš¡ï¸ ç®—æ³•

排åº

10000
排åºç®—法 平凿—¶é—´å¤æ‚度 æœ€å·®æ—¶é—´å¤æ‚度 ç©ºé—´å¤æ‚度 æ•°æ®å¯¹è±¡ç¨³å®šæ€§
å†’æ³¡æŽ’åº O(n2) O(n2) O(1) 稳定
é€‰æ‹©æŽ’åº O(n2) O(n2) O(1) 数组ä¸ç¨³å®šã€é“¾è¡¨ç¨³å®š
æ’å…¥æŽ’åº O(n2) O(n2) O(1) 稳定
å¿«é€ŸæŽ’åº O(n*log2n) O(n2) O(log2n) ä¸ç¨³å®š
å †æŽ’åº O(n*log2n) O(n*log2n) O(1) ä¸ç¨³å®š
å½’å¹¶æŽ’åº O(n*log2n) O(n*log2n) O(n) 稳定
å¸Œå°”æŽ’åº O(n*log2n) O(n2) O(1) ä¸ç¨³å®š
è®¡æ•°æŽ’åº O(n+m) O(n+m) O(n+m) 稳定
æ¡¶æŽ’åº O(n) O(n) O(m) 稳定
åŸºæ•°æŽ’åº O(k*n) O(n2) 稳定
  • 凿Œ‰ä»Žå°åˆ°å¤§æŽ’列
  • k:代表数值中的 “数ä½â€ 个数
  • n:代表数æ®è§„模
  • m:代表数æ®çš„æœ€å¤§å€¼å‡æœ€å°å€¼
  • æ¥è‡ªï¼šwikipedia . 排åºç®—法

查找

查找算法 平凿—¶é—´å¤æ‚度 ç©ºé—´å¤æ‚度 查找æ¡ä»¶
é¡ºåºæŸ¥æ‰¾ O(n) O(1) æ— åºæˆ–有åº
äºŒåˆ†æŸ¥æ‰¾ï¼ˆæŠ˜åŠæŸ¥æ‰¾ï¼‰ O(log2n) O(1) 有åº
æ’值查找 O(log2(log2n)) O(1) 有åº
æ–æ³¢é‚£å¥‘查找 O(log2n) O(1) 有åº
哈希查找 O(1) O(n) æ— åºæˆ–有åº
äºŒå‰æŸ¥æ‰¾æ ‘ï¼ˆäºŒå‰æœç´¢æ ‘查找) O(log2n)
红黑树 O(log2n)
2-3æ ‘ O(log2n - log3n)
Bæ ‘/B+æ ‘ O(log2n)

图æœç´¢ç®—法

图æœç´¢ç®—法 æ•°æ®ç»“æž„ éåŽ†æ—¶é—´å¤æ‚度 ç©ºé—´å¤æ‚度
BFS广度优先æœç´¢ 邻接矩阵
邻接链表
O(|v|2)
O(|v|+|E|)
O(|v|2)
O(|v|+|E|)
DFS深度优先æœç´¢ 邻接矩阵
邻接链表
O(|v|2)
O(|v|+|E|)
O(|v|2)
O(|v|+|E|)

其他算法

算法 æ€æƒ³ 应用
分治法 æŠŠä¸€ä¸ªå¤æ‚的问题分æˆä¸¤ä¸ªæˆ–æ›´å¤šçš„ç›¸åŒæˆ–相似的å­é—®é¢˜ï¼Œç›´åˆ°æœ€åŽå­é—®é¢˜å¯ä»¥ç®€å•的直接求解,原问题的解å³å­é—®é¢˜çš„解的åˆå¹¶ å¾ªçŽ¯èµ›æ—¥ç¨‹å®‰æŽ’é—®é¢˜ã€æŽ’åºç®—法(快速排åºã€å½’并排åºï¼‰
动æ€è§„划 通过把原问题分解为相对简å•çš„å­é—®é¢˜çš„æ–¹å¼æ±‚è§£å¤æ‚问题的方法,适用于有é‡å å­é—®é¢˜å’Œæœ€ä¼˜å­ç»“构性质的问题 èƒŒåŒ…é—®é¢˜ã€æ–波那契数列
贪心法 一ç§åœ¨æ¯ä¸€æ­¥é€‰æ‹©ä¸­éƒ½é‡‡å–在当å‰çжæ€ä¸‹æœ€å¥½æˆ–æœ€ä¼˜ï¼ˆå³æœ€æœ‰åˆ©ï¼‰çš„选择,从而希望导致结果是最好或最优的算法 æ—…è¡ŒæŽ¨é”€å‘˜é—®é¢˜ï¼ˆæœ€çŸ­è·¯å¾„é—®é¢˜ï¼‰ã€æœ€å°ç”Ÿæˆæ ‘ã€å“ˆå¤«æ›¼ç¼–ç 

â“ Problems

Single Problem

Leetcode Problems

剑指 Offer

Cracking the Coding Interview 程åºå‘˜é¢è¯•金典

牛客网

💻 æ“作系统

进程与线程

对于有线程系统:

  • 进程是资æºåˆ†é…的独立å•ä½
  • 线程是资æºè°ƒåº¦çš„独立å•ä½

对于无线程系统:

  • 进程是资æºè°ƒåº¦ã€åˆ†é…的独立å•ä½

进程之间的通信方å¼ä»¥åŠä¼˜ç¼ºç‚¹

  • 管é“(PIPE)
    • 有å管é“:一ç§åŠåŒå·¥çš„通信方å¼ï¼Œå®ƒå…许无亲缘关系进程间的通信
      • 优点:å¯ä»¥å®žçް任æ„关系的进程间的通信
      • 缺点:
        1. 长期存于系统中,使用ä¸å½“容易出错
        2. 缓冲区有é™
    • æ— å管é“:一ç§åŠåŒå·¥çš„通信方å¼ï¼Œåªèƒ½åœ¨å…·æœ‰äº²ç¼˜å…³ç³»çš„进程间使用(父å­è¿›ç¨‹ï¼‰
      • ä¼˜ç‚¹ï¼šç®€å•æ–¹ä¾¿
      • 缺点:
        1. å±€é™äºŽå•å‘通信
        2. åªèƒ½åˆ›å»ºåœ¨å®ƒçš„进程以åŠå…¶æœ‰äº²ç¼˜å…³ç³»çš„进程之间
        3. 缓冲区有é™
  • ä¿¡å·é‡ï¼ˆSemaphore):一个计数器,å¯ä»¥ç”¨æ¥æŽ§åˆ¶å¤šä¸ªçº¿ç¨‹å¯¹å…±äº«èµ„æºçš„访问
    • 优点:å¯ä»¥åŒæ­¥è¿›ç¨‹
    • 缺点:信å·é‡æœ‰é™
  • ä¿¡å·ï¼ˆSignalï¼‰ï¼šä¸€ç§æ¯”è¾ƒå¤æ‚的通信方å¼ï¼Œç”¨äºŽé€šçŸ¥æŽ¥æ”¶è¿›ç¨‹æŸä¸ªäº‹ä»¶å·²ç»å‘生
  • 消æ¯é˜Ÿåˆ—(Message Queue):是消æ¯çš„链表,存放在内核中并由消æ¯é˜Ÿåˆ—标识符标识
    • 优点:å¯ä»¥å®žçް任æ„进程间的通信,并通过系统调用函数æ¥å®žçŽ°æ¶ˆæ¯å‘é€å’ŒæŽ¥æ”¶ä¹‹é—´çš„åŒæ­¥ï¼Œæ— éœ€è€ƒè™‘åŒæ­¥é—®é¢˜ï¼Œæ–¹ä¾¿
    • 缺点:信æ¯çš„å¤åˆ¶éœ€è¦é¢å¤–消耗 CPU 的时间,ä¸é€‚宜于信æ¯é‡å¤§æˆ–æ“作频ç¹çš„场åˆ
  • 共享内存(Shared Memory):映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但多个进程都å¯ä»¥è®¿é—®
    • 优点:无须å¤åˆ¶ï¼Œå¿«æ·ï¼Œä¿¡æ¯é‡å¤§
    • 缺点:
      1. 通信是通过将共享空间缓冲区直接附加到进程的虚拟地å€ç©ºé—´ä¸­æ¥å®žçŽ°çš„ï¼Œå› æ­¤è¿›ç¨‹é—´çš„è¯»å†™æ“ä½œçš„åŒæ­¥é—®é¢˜
      2. 利用内存缓冲区直接交æ¢ä¿¡æ¯ï¼Œå†…存的实体存在于计算机中,åªèƒ½åŒä¸€ä¸ªè®¡ç®—æœºç³»ç»Ÿä¸­çš„è¯¸å¤šè¿›ç¨‹å…±äº«ï¼Œä¸æ–¹ä¾¿ç½‘络通信
  • 套接字(Socket):å¯ç”¨äºŽä¸åŒè®¡ç®—机间的进程通信
    • 优点:
      1. 传输数æ®ä¸ºå­—节级,传输数æ®å¯è‡ªå®šä¹‰ï¼Œæ•°æ®é‡å°æ•ˆçŽ‡é«˜
      2. ä¼ è¾“æ•°æ®æ—¶é—´çŸ­ï¼Œæ€§èƒ½é«˜
      3. 适åˆäºŽå®¢æˆ·ç«¯å’ŒæœåŠ¡å™¨ç«¯ä¹‹é—´ä¿¡æ¯å®žæ—¶äº¤äº’
      4. å¯ä»¥åР坆,æ•°æ®å®‰å…¨æ€§å¼º
    • 缺点:需对传输的数æ®è¿›è¡Œè§£æžï¼Œè½¬åŒ–æˆåº”用级的数æ®ã€‚

线程之间的通信方å¼

  • 锿œºåˆ¶ï¼šåŒ…括互斥é”/é‡ï¼ˆmutex)ã€è¯»å†™é”(reader-writer lock)ã€è‡ªæ—‹é”(spin lockï¼‰ã€æ¡ä»¶å˜é‡ï¼ˆcondition)
    • 互斥é”/é‡ï¼ˆmutex):æä¾›äº†ä»¥æŽ’ä»–æ–¹å¼é˜²æ­¢æ•°æ®ç»“构被并å‘修改的方法。
    • 读写é”(reader-writer lock):å…è®¸å¤šä¸ªçº¿ç¨‹åŒæ—¶è¯»å…±äº«æ•°æ®ï¼Œè€Œå¯¹å†™æ“作是互斥的。
    • 自旋é”(spin lock)与互斥é”ç±»ä¼¼ï¼Œéƒ½æ˜¯ä¸ºäº†ä¿æŠ¤å…±äº«èµ„æºã€‚äº’æ–¥é”æ˜¯å½“资æºè¢«å ç”¨ï¼Œç”³è¯·è€…进入ç¡çœ çжæ€ï¼›è€Œè‡ªæ—‹é”åˆ™å¾ªçŽ¯æ£€æµ‹ä¿æŒè€…是å¦å·²ç»é‡Šæ”¾é”。
    • æ¡ä»¶å˜é‡ï¼ˆcondition):å¯ä»¥ä»¥åŽŸå­çš„æ–¹å¼é˜»å¡žè¿›ç¨‹ï¼Œç›´åˆ°æŸä¸ªç‰¹å®šæ¡ä»¶ä¸ºçœŸä¸ºæ­¢ã€‚对æ¡ä»¶çš„æµ‹è¯•是在互斥é”çš„ä¿æŠ¤ä¸‹è¿›è¡Œçš„ã€‚æ¡ä»¶å˜é‡å§‹ç»ˆä¸Žäº’æ–¥é”一起使用。
  • ä¿¡å·é‡æœºåˆ¶(Semaphore)
    • æ— å线程信å·é‡
    • 命å线程信å·é‡
  • ä¿¡å·æœºåˆ¶(Signal):类似进程间的信å·å¤„ç†
  • å±éšœï¼ˆbarrier):å±éšœå…许æ¯ä¸ªçº¿ç¨‹ç­‰å¾…,直到所有的åˆä½œçº¿ç¨‹éƒ½è¾¾åˆ°æŸä¸€ç‚¹ï¼Œç„¶åŽä»Žè¯¥ç‚¹ç»§ç»­æ‰§è¡Œã€‚

çº¿ç¨‹é—´çš„é€šä¿¡ç›®çš„ä¸»è¦æ˜¯ç”¨äºŽçº¿ç¨‹åŒæ­¥ï¼Œæ‰€ä»¥çº¿ç¨‹æ²¡æœ‰åƒè¿›ç¨‹é€šä¿¡ä¸­çš„用于数æ®äº¤æ¢çš„通信机制

进程之间的通信方å¼ä»¥åŠä¼˜ç¼ºç‚¹æ¥æºäºŽï¼šè¿›ç¨‹çº¿ç¨‹é¢è¯•题总结

è¿›ç¨‹ä¹‹é—´ç§æœ‰å’Œå…±äº«çš„资æº

  • ç§æœ‰ï¼šåœ°å€ç©ºé—´ã€å †ã€å…¨å±€å˜é‡ã€æ ˆã€å¯„存器
  • å…±äº«ï¼šä»£ç æ®µï¼Œå…¬å…±æ•°æ®ï¼Œè¿›ç¨‹ç›®å½•,进程 ID

çº¿ç¨‹ä¹‹é—´ç§æœ‰å’Œå…±äº«çš„资æº

  • ç§æœ‰ï¼šçº¿ç¨‹æ ˆï¼Œå¯„存器,程åºè®¡æ•°å™¨
  • 共享:堆,地å€ç©ºé—´ï¼Œå…¨å±€å˜é‡ï¼Œé™æ€å˜é‡

多进程与多线程间的对比ã€ä¼˜åŠ£ä¸Žé€‰æ‹©

对比
对比维度 多进程 多线程 总结
æ•°æ®å…±äº«ã€åŒæ­¥ æ•°æ®å…±äº«å¤æ‚,需è¦ç”¨ IPCï¼›æ•°æ®æ˜¯åˆ†å¼€çš„ï¼ŒåŒæ­¥ç®€å• 因为共享进程数æ®ï¼Œæ•°æ®å…±äº«ç®€å•ï¼Œä½†ä¹Ÿæ˜¯å› ä¸ºè¿™ä¸ªåŽŸå› å¯¼è‡´åŒæ­¥å¤æ‚ 儿œ‰ä¼˜åŠ¿
内存ã€CPU å ç”¨å†…存多,切æ¢å¤æ‚,CPU 利用率低 å ç”¨å†…存少,切æ¢ç®€å•,CPU 利用率高 线程å ä¼˜
创建销æ¯ã€åˆ‡æ¢ 创建销æ¯ã€åˆ‡æ¢å¤æ‚,速度慢 创建销æ¯ã€åˆ‡æ¢ç®€å•,速度很快 线程å ä¼˜
编程ã€è°ƒè¯• 编程简å•ï¼Œè°ƒè¯•ç®€å• ç¼–ç¨‹å¤æ‚ï¼Œè°ƒè¯•å¤æ‚ 进程å ä¼˜
å¯é æ€§ 进程间ä¸ä¼šäº’ç›¸å½±å“ ä¸€ä¸ªçº¿ç¨‹æŒ‚æŽ‰å°†å¯¼è‡´æ•´ä¸ªè¿›ç¨‹æŒ‚æŽ‰ 进程å ä¼˜
åˆ†å¸ƒå¼ é€‚åº”äºŽå¤šæ ¸ã€å¤šæœºåˆ†å¸ƒå¼ï¼›å¦‚æžœä¸€å°æœºå™¨ä¸å¤Ÿï¼Œæ‰©å±•åˆ°å¤šå°æœºå™¨æ¯”è¾ƒç®€å• é€‚åº”äºŽå¤šæ ¸åˆ†å¸ƒå¼ è¿›ç¨‹å ä¼˜
优劣
优劣 多进程 多线程
优点 编程ã€è°ƒè¯•简å•,å¯é æ€§è¾ƒé«˜ 创建ã€é”€æ¯ã€åˆ‡æ¢é€Ÿåº¦å¿«ï¼Œå†…å­˜ã€èµ„æºå ç”¨å°
缺点 创建ã€é”€æ¯ã€åˆ‡æ¢é€Ÿåº¦æ…¢ï¼Œå†…å­˜ã€èµ„æºå ç”¨å¤§ 编程ã€è°ƒè¯•夿‚,å¯é æ€§è¾ƒå·®
选择
  • 需è¦é¢‘ç¹åˆ›å»ºé”€æ¯çš„优先用线程
  • 需è¦è¿›è¡Œå¤§é‡è®¡ç®—的优先使用线程
  • 强相关的处ç†ç”¨çº¿ç¨‹ï¼Œå¼±ç›¸å…³çš„处ç†ç”¨è¿›ç¨‹
  • å¯èƒ½è¦æ‰©å±•到多机分布的用进程,多核分布的用线程
  • éƒ½æ»¡è¶³éœ€æ±‚çš„æƒ…å†µä¸‹ï¼Œç”¨ä½ æœ€ç†Ÿæ‚‰ã€æœ€æ‹¿æ‰‹çš„æ–¹å¼

多进程与多线程间的对比ã€ä¼˜åŠ£ä¸Žé€‰æ‹©æ¥è‡ªï¼šå¤šçº¿ç¨‹è¿˜æ˜¯å¤šè¿›ç¨‹çš„选择åŠåŒºåˆ«

Linux å†…æ ¸çš„åŒæ­¥æ–¹å¼

原因

在现代æ“作系统里,åŒä¸€æ—¶é—´å¯èƒ½æœ‰å¤šä¸ªå†…核执行æµåœ¨æ‰§è¡Œï¼Œå› æ­¤å†…核其实åƒå¤šè¿›ç¨‹å¤šçº¿ç¨‹ç¼–程一样也需è¦ä¸€äº›åŒæ­¥æœºåˆ¶æ¥åŒæ­¥å„执行å•元对共享数æ®çš„访问。尤其是在多处ç†å™¨ç³»ç»Ÿä¸Šï¼Œæ›´éœ€è¦ä¸€äº›åŒæ­¥æœºåˆ¶æ¥åŒæ­¥ä¸åŒå¤„ç†å™¨ä¸Šçš„æ‰§è¡Œå•元对共享的数æ®çš„访问。

åŒæ­¥æ–¹å¼

  • åŽŸå­æ“作
  • ä¿¡å·é‡ï¼ˆsemaphore)
  • 读写信å·é‡ï¼ˆrw_semaphore)
  • 自旋é”(spinlock)
  • 大内核é”(BKL,Big Kernel Lock)
  • 读写é”(rwlock)
  • 大读者é”(brlock-Big Reader Lock)
  • 读-æ‹·è´ä¿®æ”¹(RCU,Read-Copy Update)
  • 顺åºé”(seqlock)

æ¥è‡ªï¼šLinux å†…æ ¸çš„åŒæ­¥æœºåˆ¶ï¼Œç¬¬ 1 部分ã€Linux å†…æ ¸çš„åŒæ­¥æœºåˆ¶ï¼Œç¬¬ 2 部分

æ­»é”

原因

  • 系统资æºä¸è¶³
  • 资æºåˆ†é…ä¸å½“
  • 进程è¿è¡ŒæŽ¨è¿›é¡ºåºä¸åˆé€‚

产生æ¡ä»¶

  • 互斥
  • è¯·æ±‚å’Œä¿æŒ
  • ä¸å‰¥å¤º
  • 环路

预防

  • 打破互斥æ¡ä»¶ï¼šæ”¹é€ ç‹¬å æ€§èµ„æºä¸ºè™šæ‹Ÿèµ„æºï¼Œå¤§éƒ¨åˆ†èµ„æºå·²æ— æ³•改造。
  • 打破ä¸å¯æŠ¢å æ¡ä»¶ï¼šå½“ä¸€è¿›ç¨‹å æœ‰ä¸€ç‹¬å æ€§èµ„æºåŽåˆç”³è¯·ä¸€ç‹¬å æ€§èµ„æºè€Œæ— æ³•æ»¡è¶³ï¼Œåˆ™é€€å‡ºåŽŸå æœ‰çš„资æºã€‚
  • æ‰“ç ´å æœ‰ä¸”申请æ¡ä»¶ï¼šé‡‡ç”¨èµ„æºé¢„先分é…策略,å³è¿›ç¨‹è¿è¡Œå‰ç”³è¯·å…¨éƒ¨èµ„æºï¼Œæ»¡è¶³åˆ™è¿è¡Œï¼Œä¸ç„¶å°±ç­‰å¾…,这样就ä¸ä¼šå æœ‰ä¸”申请。
  • 打破循环等待æ¡ä»¶ï¼šå®žçŽ°èµ„æºæœ‰åºåˆ†é…策略,对所有设备实现分类编å·ï¼Œæ‰€æœ‰è¿›ç¨‹åªèƒ½é‡‡ç”¨æŒ‰åºå·é€’增的形å¼ç”³è¯·èµ„æºã€‚
  • 有åºèµ„æºåˆ†é…法
  • 银行家算法

文件系统

  • Windows:FCB 表 + FAT + ä½å›¾
  • Unix:inode + æ··åˆç´¢å¼• + æˆç»„链接

主机字节åºä¸Žç½‘络字节åº

主机字节åºï¼ˆCPU 字节åºï¼‰

概念

主机字节åºåˆå« CPU 字节åºï¼Œå…¶ä¸æ˜¯ç”±æ“作系统决定的,而是由 CPU 指令集架构决定的。主机字节åºåˆ†ä¸ºä¸¤ç§ï¼š

  • 大端字节åºï¼ˆBig Endian):高åºå­—节存储在低ä½åœ°å€ï¼Œä½Žåºå­—节存储在高ä½åœ°å€
  • å°ç«¯å­—节åºï¼ˆLittle Endian):高åºå­—节存储在高ä½åœ°å€ï¼Œä½Žåºå­—节存储在低ä½åœ°å€
存储方å¼

32 使•´æ•° 0x12345678 是从起始ä½ç½®ä¸º 0x00 的地å€å¼€å§‹å­˜æ”¾ï¼Œåˆ™ï¼š

å†…å­˜åœ°å€ 0x00 0x01 0x02 0x03
大端 12 34 56 78
å°ç«¯ 78 56 34 12

大端å°ç«¯å›¾ç‰‡

å¤§ç«¯åº å°ç«¯åº

判断大端å°ç«¯

判断大端å°ç«¯

å¯ä»¥è¿™æ ·åˆ¤æ–­è‡ªå·± CPU å­—èŠ‚åºæ˜¯å¤§ç«¯è¿˜æ˜¯å°ç«¯ï¼š

#include <iostream>
using namespace std;

int main()
{
	int i = 0x12345678;

	if (*((char*)&i) == 0x12)
		cout << "大端" << endl;
	else	
		cout << "å°ç«¯" << endl;

	return 0;
}
儿ž¶æž„处ç†å™¨çš„字节åº
  • x86(Intelã€AMD)ã€MOS Technology 6502ã€Z80ã€VAXã€PDP-11 等处ç†å™¨ä¸ºå°ç«¯åºï¼›
  • Motorola 6800ã€Motorola 68000ã€PowerPC 970ã€System/370ã€SPARC(除 V9 外)等处ç†å™¨ä¸ºå¤§ç«¯åºï¼›
  • ARM(默认å°ç«¯åºï¼‰ã€PowerPC(除 PowerPC 970 外)ã€DEC Alphaã€SPARC V9ã€MIPSã€PA-RISC åŠ IA64 çš„å­—èŠ‚åºæ˜¯å¯é…置的。

网络字节åº

ç½‘ç»œå­—èŠ‚é¡ºåºæ˜¯ TCP/IP ä¸­è§„å®šå¥½çš„ä¸€ç§æ•°æ®è¡¨ç¤ºæ ¼å¼ï¼Œå®ƒä¸Žå…·ä½“çš„ CPU ç±»åž‹ã€æ“作系统等无关,从而å¯ä»¥ä¿è¯æ•°æ®åœ¨ä¸åŒä¸»æœºä¹‹é—´ä¼ è¾“时能够被正确解释。

网络字节顺åºé‡‡ç”¨ï¼šå¤§ç«¯ï¼ˆBig Endian)排列方å¼ã€‚

页é¢ç½®æ¢ç®—法

åœ¨åœ°å€æ˜ å°„过程中,若在页é¢ä¸­å‘现所è¦è®¿é—®çš„页é¢ä¸åœ¨å†…存中,则产生缺页中断。当å‘生缺页中断时,如果æ“作系统内存中没有空闲页é¢ï¼Œåˆ™æ“作系统必须在内存选择一个页é¢å°†å…¶ç§»å‡ºå†…存,以便为å³å°†è°ƒå…¥çš„页é¢è®©å‡ºç©ºé—´ã€‚而用æ¥é€‰æ‹©æ·˜æ±°å“ªä¸€é¡µçš„规则å«åšé¡µé¢ç½®æ¢ç®—法。

分类

  • 全局置æ¢ï¼šåœ¨æ•´ä¸ªå†…存空间置æ¢
  • 局部置æ¢ï¼šåœ¨æœ¬è¿›ç¨‹ä¸­è¿›è¡Œç½®æ¢

算法

全局:

  • 工作集算法
  • 缺页率置æ¢ç®—法

局部:

  • 最佳置æ¢ç®—法(OPT)
  • 先进先出置æ¢ç®—法(FIFO)
  • 最近最久未使用(LRU)算法
  • 时钟(Clock)置æ¢ç®—法

â˜ï¸ 计算机网络

本节部分知识点æ¥è‡ªã€Šè®¡ç®—机网络(第 7 版)》

计算机网络体系结构:

计算机网络体系结构

å„层作用åŠåè®®

分层 作用 åè®®
物ç†å±‚ 通过媒介传输比特,确定机械åŠç”µæ°”规范(比特 Bit) RJ45ã€CLOCKã€IEEE802.3(中继器,集线器)
æ•°æ®é“¾è·¯å±‚ 将比特组装æˆå¸§å’Œç‚¹åˆ°ç‚¹çš„传递(帧 Frame) PPPã€FRã€HDLCã€VLANã€MACï¼ˆç½‘æ¡¥ï¼Œäº¤æ¢æœºï¼‰
网络层 负责数æ®åŒ…从æºåˆ°å®¿çš„传递和网际互连(包 Packet) IPã€ICMPã€ARPã€RARPã€OSPFã€IPXã€RIPã€IGRP(路由器)
è¿è¾“层 æä¾›ç«¯åˆ°ç«¯çš„å¯é æŠ¥æ–‡ä¼ é€’和错误æ¢å¤ï¼ˆ 段Segment) TCPã€UDPã€SPX
会è¯å±‚ 建立ã€ç®¡ç†å’Œç»ˆæ­¢ä¼šè¯ï¼ˆä¼šè¯å议数æ®å•å…ƒ SPDU) NFSã€SQLã€NETBIOSã€RPC
表示层 对数æ®è¿›è¡Œç¿»è¯‘ã€åŠ å¯†å’ŒåŽ‹ç¼©ï¼ˆè¡¨ç¤ºå议数æ®å•å…ƒ PPDU) JPEGã€MPEGã€ASII
应用层 å…许访问OSI环境的手段(应用å议数æ®å•å…ƒ APDU) FTPã€DNSã€Telnetã€SMTPã€HTTPã€WWWã€NFS

物ç†å±‚

  • 传输数æ®çš„å•ä½ï¼šæ¯”特
  • æ•°æ®ä¼ è¾“系统:æºç³»ç»Ÿï¼ˆæºç‚¹ã€å‘é€å™¨ï¼‰ --> 传输系统 --> 目的系统(接收器ã€ç»ˆç‚¹ï¼‰

通é“:

  • å•å‘通é“(å•工通é“ï¼‰ï¼šåªæœ‰ä¸€ä¸ªæ–¹å‘é€šä¿¡ï¼Œæ²¡æœ‰åæ–¹å‘交互,如广播
  • åŒå‘交替通信(åŠåŒå·¥é€šä¿¡ï¼‰ï¼šé€šä¿¡åŒæ–¹éƒ½å¯å‘消æ¯ï¼Œä½†ä¸èƒ½åŒæ—¶å‘逿ˆ–接收
  • åŒå‘åŒæ—¶é€šä¿¡ï¼ˆå…¨åŒå·¥é€šä¿¡ï¼‰ï¼šé€šä¿¡åŒæ–¹å¯ä»¥åŒæ—¶å‘é€å’ŒæŽ¥æ”¶ä¿¡æ¯

通é“å¤ç”¨æŠ€æœ¯ï¼š

  • 频分å¤ç”¨ï¼ˆFDM,Frequency Division Multiplexing):ä¸åŒç”¨æˆ·åœ¨ä¸åŒé¢‘å¸¦ï¼Œæ‰€ç”¨ç”¨æˆ·åœ¨åŒæ ·æ—¶é—´å ç”¨ä¸åŒå¸¦å®½èµ„æº
  • 时分å¤ç”¨ï¼ˆTDM,Time Division Multiplexing):ä¸åŒç”¨æˆ·åœ¨åŒä¸€æ—¶é—´æ®µçš„ä¸åŒæ—¶é—´ç‰‡ï¼Œæ‰€æœ‰ç”¨æˆ·åœ¨ä¸åŒæ—¶é—´å ç”¨åŒæ ·çš„频带宽度
  • 波分å¤ç”¨ï¼ˆWDM,Wavelength Division Multiplexing):光的频分å¤ç”¨
  • ç åˆ†å¤ç”¨ï¼ˆCDM,Code Division Multiplexing):ä¸åŒç”¨æˆ·ä½¿ç”¨ä¸åŒçš„ç ï¼Œå¯ä»¥åœ¨åŒæ ·æ—¶é—´ä½¿ç”¨åŒæ ·é¢‘带通信

æ•°æ®é“¾è·¯å±‚

主è¦ä¿¡é“:

  • 点对点信é“
  • 广播信é“

点对点信é“

  • æ•°æ®å•元:帧

三个基本问题:

  • å°è£…æˆå¸§ï¼šæŠŠç½‘络层的 IP æ•°æ®æŠ¥å°è£…æˆå¸§ï¼ŒSOH - æ•°æ®éƒ¨åˆ† - EOT
  • 逿˜Žä¼ è¾“:ä¸ç®¡æ•°æ®éƒ¨åˆ†ä»€ä¹ˆå­—符,都能传输出去;å¯ä»¥é€šè¿‡å­—节填充方法解决(冲çªå­—符å‰åŠ è½¬ä¹‰å­—ç¬¦ï¼‰
  • 差错检测:é™ä½Žè¯¯ç çŽ‡ï¼ˆBER,Bit Error Rate),广泛使用循环冗余检测(CRC,Cyclic Redundancy Check)

点对点å议(Point-to-Point Protocol):

  • 点对点å议(Point-to-Point Protocol):用户计算机和 ISP 通信时所使用的åè®®

广播信é“

广播通信:

  • 硬件地å€ï¼ˆç‰©ç†åœ°å€ã€MAC 地å€ï¼‰
  • 啿’­ï¼ˆunicast)帧(一对一):收到的帧的 MAC 地å€ä¸Žæœ¬ç«™çš„硬件地å€ç›¸åŒ
  • 广播(broadcast)帧(一对全体):å‘é€ç»™æœ¬å±€åŸŸç½‘上所有站点的帧
  • 多播(multicast)帧(一对多):å‘é€ç»™æœ¬å±€åŸŸç½‘上一部分站点的帧

网络层

  • IP(Internet Protocol,网际å议)是为计算机网络相互连接进行通信而设计的å议。
  • ARP(Address Resolution Protocol,地å€è§£æžå议)
  • ICMP(Internet Control Message Protocol,网际控制报文å议)
  • IGMP(Internet Group Management Protocol,网际组管ç†å议)

IP 地å€åˆ†ç±»ï¼š

  • IP åœ°å€ ::= {<网络å·>,<主机å·>}
IP 地å€ç±»åˆ« ç½‘ç»œå· ç½‘ç»œèŒƒå›´ ä¸»æœºå· IP 地å€èŒƒå›´
A ç±» 8bit,第一ä½å›ºå®šä¸º 0 0 —— 127 24bit 1.0.0.0 —— 127.255.255.255
B ç±» 16bit,å‰ä¸¤ä½å›ºå®šä¸º 10 128.0 —— 191.255 16bit 128.0.0.0 —— 191.255.255.255
C ç±» 24bit,å‰ä¸‰ä½å›ºå®šä¸º 110 192.0.0 —— 223.255.255 8bit 192.0.0.0 —— 223.255.255.255
D ç±» å‰å››ä½å›ºå®šä¸º 1110,åŽé¢ä¸ºå¤šæ’­åœ°å€
E ç±» å‰äº”ä½å›ºå®šä¸º 11110,åŽé¢ä¿ç•™ä¸ºä»ŠåŽæ‰€ç”¨

IP æ•°æ®æŠ¥æ ¼å¼ï¼š

IP æ•°æ®æŠ¥æ ¼å¼

ICMP 网际控制报文åè®®

ICMP 报文格å¼ï¼š

ICMP 报文格å¼

应用:

  • PING(Packet InterNet Groper,分组网间探测)测试两个主机之间的连通性
  • TTL(Time To Live,生存时间)该字段指定 IP 包被路由器丢弃之å‰å…许通过的最大网段数é‡

内部网关åè®®

  • RIP(Routing Information Protocol,路由信æ¯å议)
  • OSPF(Open Sortest Path First,开放最短路径优先)

外部网关åè®®

  • BGP(Border Gateway Protocol,边界网关å议)

IP多播

  • IGMP(Internet Group Management Protocol,网际组管ç†å议)
  • 多播路由选择åè®®

VPN 和 NAT

  • VPN(Virtual Private Network,虚拟专用网)
  • NAT(Network Address Translation,网络地å€è½¬æ¢ï¼‰

路由表包å«ä»€ä¹ˆï¼Ÿ

  1. 网络 ID(Network ID, Network number):就是目标地å€çš„网络 ID。
  2. å­ç½‘掩ç ï¼ˆsubnet mask):用æ¥åˆ¤æ–­ IP 所属网络
  3. 下一跳地å€/接å£ï¼ˆNext hop / interface):就是数æ®åœ¨å‘é€åˆ°ç›®æ ‡åœ°å€çš„æ—…途中下一站的地å€ã€‚其中 interface æŒ‡å‘ next hop(å³ä¸ºä¸‹ä¸€ä¸ª route)。一个自治系统(AS, Autonomous system)中的 route 应该包å«åŒºåŸŸå†…所有的å­ç½‘络,而默认网关(Network id: 0.0.0.0, Netmask: 0.0.0.0)指å‘自治系统的出å£ã€‚

æ ¹æ®åº”用和执行的ä¸åŒï¼Œè·¯ç”±è¡¨å¯èƒ½å«æœ‰å¦‚下附加信æ¯ï¼š

  1. 花费(Cost):就是数æ®å‘é€è¿‡ç¨‹ä¸­é€šè¿‡è·¯å¾„所需è¦çš„花费。
  2. 路由的æœåŠ¡è´¨é‡
  3. 路由中需è¦è¿‡æ»¤çš„出/入连接列表

è¿è¾“层

å议:

  • TCP(Transmission Control Protocol,传输控制å议)
  • UDP(User Datagram Protocolï¼Œç”¨æˆ·æ•°æ®æŠ¥å议)

端å£ï¼š

åº”ç”¨ç¨‹åº FTP TELNET SMTP DNS TFTP HTTP HTTPS SNMP
端å£å· 21 23 25 53 69 80 443 161

TCP

  • TCP(Transmission Control Protocol,传输控制å议)是一ç§é¢å‘连接的ã€å¯é çš„ã€åŸºäºŽå­—节æµçš„传输层通信å议,其传输的å•使˜¯æŠ¥æ–‡æ®µã€‚

特å¾ï¼š

  • é¢å‘连接
  • åªèƒ½ç‚¹å¯¹ç‚¹ï¼ˆä¸€å¯¹ä¸€ï¼‰é€šä¿¡
  • å¯é äº¤äº’
  • å…¨åŒå·¥é€šä¿¡
  • é¢å‘字节æµ

TCP 如何ä¿è¯å¯é ä¼ è¾“:

  • 确认和超时é‡ä¼ 
  • æ•°æ®åˆç†åˆ†ç‰‡å’ŒæŽ’åº
  • æµé‡æŽ§åˆ¶
  • 拥塞控制
  • æ•°æ®æ ¡éªŒ

TCP 报文结构

TCP 报文

TCP 首部

TCP 首部

TCPï¼šçŠ¶æ€æŽ§åˆ¶ç ï¼ˆCode,Control Flagï¼‰ï¼Œå  6 比特,å«ä¹‰å¦‚下:

  • URG:紧急比特(urgent),当 URGï¼1 时,表明紧急指针字段有效,代表该å°åŒ…为紧急å°åŒ…。它告诉系统此报文段中有紧急数æ®ï¼Œåº”尽快传é€(相当于高优先级的数æ®), 且上图中的 Urgent Pointer 字段也会被å¯ç”¨ã€‚
  • ACK:确认比特(Acknowledgeï¼‰ã€‚åªæœ‰å½“ ACKï¼1 时确认å·å­—æ®µæ‰æœ‰æ•ˆï¼Œä»£è¡¨è¿™ä¸ªå°åŒ…为确认å°åŒ…。当 ACKï¼0 æ—¶ï¼Œç¡®è®¤å·æ— æ•ˆã€‚
  • PSH:(Push function)若为 1 æ—¶ï¼Œä»£è¡¨è¦æ±‚对方立å³ä¼ é€ç¼“冲区内的其他对应å°åŒ…,而无需等缓冲满了æ‰é€ã€‚
  • RST:å¤ä½æ¯”特(Reset),当 RSTï¼1 时,表明 TCP 连接中出现严é‡å·®é”™ï¼ˆå¦‚由于主机崩溃或其他原因),必须释放连接,然åŽå†é‡æ–°å»ºç«‹è¿è¾“连接。
  • SYNï¼šåŒæ­¥æ¯”特(Synchronous),SYN 置为 1ï¼Œå°±è¡¨ç¤ºè¿™æ˜¯ä¸€ä¸ªè¿žæŽ¥è¯·æ±‚æˆ–è¿žæŽ¥æŽ¥å—æŠ¥æ–‡ï¼Œé€šå¸¸å¸¦æœ‰ SYN 标志的å°åŒ…表示『主动ã€è¦è¿žæŽ¥åˆ°å¯¹æ–¹çš„æ„æ€ã€‚
  • FIN:终止比特(Final),用æ¥é‡Šæ”¾ä¸€ä¸ªè¿žæŽ¥ã€‚当 FINï¼1 时,表明此报文段的å‘é€ç«¯çš„æ•°æ®å·²å‘é€å®Œæ¯•ï¼Œå¹¶è¦æ±‚释放è¿è¾“连接。

UDP

  • UDP(User Datagram Protocolï¼Œç”¨æˆ·æ•°æ®æŠ¥å议)是 OSI(Open System Interconnection 开放å¼ç³»ç»Ÿäº’è”) å‚è€ƒæ¨¡åž‹ä¸­ä¸€ç§æ— è¿žæŽ¥çš„传输层å议,æä¾›é¢å‘事务的简å•ä¸å¯é ä¿¡æ¯ä¼ é€æœåŠ¡ï¼Œå…¶ä¼ è¾“çš„å•使˜¯ç”¨æˆ·æ•°æ®æŠ¥ã€‚

特å¾ï¼š

  • 无连接
  • 尽最大努力交付
  • é¢å‘报文
  • 没有拥塞控制
  • 支æŒä¸€å¯¹ä¸€ã€ä¸€å¯¹å¤šã€å¤šå¯¹ä¸€ã€å¤šå¯¹å¤šçš„交互通信
  • 首部开销å°

UDP 报文结构

UDP 报文

UDP 首部

UDP 首部

TCP/UDP å›¾ç‰‡æ¥æºäºŽï¼šhttps://github.com/JerryC8080/understand-tcp-udp

TCP 与 UDP 的区别

  1. TCP é¢å‘连接,UDP 是无连接的;
  2. TCP æä¾›å¯é çš„æœåŠ¡ï¼Œä¹Ÿå°±æ˜¯è¯´ï¼Œé€šè¿‡ TCP 连接传é€çš„æ•°æ®ï¼Œæ— å·®é”™ï¼Œä¸ä¸¢å¤±ï¼Œä¸é‡å¤ï¼Œä¸”按åºåˆ°è¾¾ï¼›UDP 尽最大努力交付,å³ä¸ä¿è¯å¯é äº¤ä»˜
  3. TCP çš„é€»è¾‘é€šä¿¡ä¿¡é“æ˜¯å…¨åŒå·¥çš„å¯é ä¿¡é“ï¼›UDP 则是ä¸å¯é ä¿¡é“
  4. æ¯ä¸€æ¡ TCP 连接åªèƒ½æ˜¯ç‚¹åˆ°ç‚¹çš„ï¼›UDP 支æŒä¸€å¯¹ä¸€ï¼Œä¸€å¯¹å¤šï¼Œå¤šå¯¹ä¸€å’Œå¤šå¯¹å¤šçš„交互通信
  5. TCP é¢å‘字节æµï¼ˆå¯èƒ½å‡ºçްé»åŒ…问题),实际上是 TCP 把数æ®çœ‹æˆä¸€è¿žä¸²æ— ç»“构的字节æµï¼›UDP 是é¢å‘报文的(ä¸ä¼šå‡ºçްé»åŒ…问题)
  6. UDP 没有拥塞控制,因此网络出现拥塞ä¸ä¼šä½¿æºä¸»æœºçš„å‘é€é€Ÿçއé™ä½Žï¼ˆå¯¹å®žæ—¶åº”用很有用,如 IP 电è¯ï¼Œå®žæ—¶è§†é¢‘会议等)
  7. TCP 首部开销20字节;UDP 的首部开销å°ï¼Œåªæœ‰ 8 个字节

TCP é»åŒ…问题

原因

TCP 是一个基于字节æµçš„传输æœåŠ¡ï¼ˆUDP 基于报文的),“æµâ€ æ„å‘³ç€ TCP æ‰€ä¼ è¾“çš„æ•°æ®æ˜¯æ²¡æœ‰è¾¹ç•Œçš„。所以å¯èƒ½ä¼šå‡ºçŽ°ä¸¤ä¸ªæ•°æ®åŒ…é»åœ¨ä¸€èµ·çš„æƒ…况。

解决
  • å‘é€å®šé•¿åŒ…。如果æ¯ä¸ªæ¶ˆæ¯çš„大å°éƒ½æ˜¯ä¸€æ ·çš„,那么在接收对等方åªè¦ç´¯è®¡æŽ¥æ”¶æ•°æ®ï¼Œç›´åˆ°æ•°æ®ç­‰äºŽä¸€ä¸ªå®šé•¿çš„æ•°å€¼å°±å°†å®ƒä½œä¸ºä¸€ä¸ªæ¶ˆæ¯ã€‚
  • 包头加上包体长度。包头是定长的 4 ä¸ªå­—èŠ‚ï¼Œè¯´æ˜Žäº†åŒ…ä½“çš„é•¿åº¦ã€‚æŽ¥æ”¶å¯¹ç­‰æ–¹å…ˆæŽ¥æ”¶åŒ…å¤´é•¿åº¦ï¼Œä¾æ®åŒ…å¤´é•¿åº¦æ¥æŽ¥æ”¶åŒ…ä½“ã€‚
  • 在数æ®åŒ…ä¹‹é—´è®¾ç½®è¾¹ç•Œï¼Œå¦‚æ·»åŠ ç‰¹æ®Šç¬¦å· \r\n 标记。FTP å议正是这么åšçš„ã€‚ä½†é—®é¢˜åœ¨äºŽå¦‚æžœæ•°æ®æ­£æ–‡ä¸­ä¹Ÿå«æœ‰ \r\n,则会误判为消æ¯çš„边界。
  • ä½¿ç”¨æ›´åŠ å¤æ‚的应用层å议。

TCP æµé‡æŽ§åˆ¶

概念

æµé‡æŽ§åˆ¶ï¼ˆflow control)就是让å‘逿–¹çš„å‘é€é€Ÿçއä¸è¦å¤ªå¿«ï¼Œè¦è®©æŽ¥æ”¶æ–¹æ¥å¾—åŠæŽ¥æ”¶ã€‚

方法

利用å¯å˜çª—å£è¿›è¡Œæµé‡æŽ§åˆ¶

TCP 拥塞控制

概念

æ‹¥å¡žæŽ§åˆ¶å°±æ˜¯é˜²æ­¢è¿‡å¤šçš„æ•°æ®æ³¨å…¥åˆ°ç½‘络中,这样å¯ä»¥ä½¿ç½‘络中的路由器或链路ä¸è‡´è¿‡è½½ã€‚

方法
  • 慢开始( slow-start )
  • 拥塞é¿å…( congestion avoidance )
  • å¿«é‡ä¼ ( fast retransmit )
  • å¿«æ¢å¤( fast recovery )

TCP的拥塞控制图

TCP 传输连接管ç†

因为 TCP ä¸‰æ¬¡æ¡æ‰‹å»ºç«‹è¿žæŽ¥ã€å››æ¬¡æŒ¥æ‰‹é‡Šæ”¾è¿žæŽ¥å¾ˆé‡è¦ï¼Œæ‰€ä»¥é™„上《计算机网络(第 7 版)-谢希ä»ã€‹ä¹¦ä¸­å¯¹æ­¤ç« çš„详细æè¿°ï¼šhttps://gitee.com/huihut/interview/raw/master/images/TCP-transport-connection-management.png

TCP ä¸‰æ¬¡æ¡æ‰‹å»ºç«‹è¿žæŽ¥

UDP 报文

ã€TCP 建立连接全过程解释】

  1. 客户端å‘é€ SYN ç»™æœåŠ¡å™¨ï¼Œè¯´æ˜Žå®¢æˆ·ç«¯è¯·æ±‚å»ºç«‹è¿žæŽ¥ï¼›
  2. æœåŠ¡ç«¯æ”¶åˆ°å®¢æˆ·ç«¯å‘çš„ SYNï¼Œå¹¶å›žå¤ SYN+ACK ç»™å®¢æˆ·ç«¯ï¼ˆåŒæ„建立连接);
  3. 客户端收到æœåŠ¡ç«¯çš„ SYN+ACK åŽï¼Œå›žå¤ ACK ç»™æœåŠ¡ç«¯ï¼ˆè¡¨ç¤ºå®¢æˆ·ç«¯æ”¶åˆ°äº†æœåŠ¡ç«¯å‘çš„åŒæ„报文);
  4. æœåŠ¡ç«¯æ”¶åˆ°å®¢æˆ·ç«¯çš„ ACK,连接已建立,å¯ä»¥æ•°æ®ä¼ è¾“。
TCP 为什么è¦è¿›è¡Œä¸‰æ¬¡æ¡æ‰‹ï¼Ÿ

ã€ç­”案一】因为信é“ä¸å¯é ï¼Œè€Œ TCP 想在ä¸å¯é ä¿¡é“上建立å¯é åœ°ä¼ è¾“,那么三次通信是ç†è®ºä¸Šçš„æœ€å°å€¼ã€‚(而 UDP 则ä¸éœ€å»ºç«‹å¯é ä¼ è¾“,因此 UDP ä¸éœ€è¦ä¸‰æ¬¡æ¡æ‰‹ã€‚)

Google Groups . TCP å»ºç«‹è¿žæŽ¥ä¸ºä»€ä¹ˆæ˜¯ä¸‰æ¬¡æ¡æ‰‹ï¼Ÿ{技术}{网络通信}

ã€ç­”æ¡ˆäºŒã€‘å› ä¸ºåŒæ–¹éƒ½éœ€è¦ç¡®è®¤å¯¹æ–¹æ”¶åˆ°äº†è‡ªå·±å‘é€çš„åºåˆ—å·ï¼Œç¡®è®¤è¿‡ç¨‹æœ€å°‘è¦è¿›è¡Œä¸‰æ¬¡é€šä¿¡ã€‚

知乎 . TCP ä¸ºä»€ä¹ˆæ˜¯ä¸‰æ¬¡æ¡æ‰‹ï¼Œè€Œä¸æ˜¯ä¸¤æ¬¡æˆ–四次?

ã€ç­”案三】为了防止已失效的连接请求报文段çªç„¶åˆä¼ é€åˆ°äº†æœåŠ¡ç«¯ï¼Œå› è€Œäº§ç”Ÿé”™è¯¯ã€‚

《计算机网络(第 7 版)-谢希ä»ã€‹

TCP 四次挥手释放连接

UDP 报文

ã€TCP 释放连接全过程解释】

  1. 客户端å‘é€ FIN ç»™æœåŠ¡å™¨ï¼Œè¯´æ˜Žå®¢æˆ·ç«¯ä¸å¿…å‘逿•°æ®ç»™æœåŠ¡å™¨äº†ï¼ˆè¯·æ±‚é‡Šæ”¾ä»Žå®¢æˆ·ç«¯åˆ°æœåŠ¡å™¨çš„è¿žæŽ¥ï¼‰ï¼›
  2. æœåŠ¡å™¨æŽ¥æ”¶åˆ°å®¢æˆ·ç«¯å‘çš„ FINï¼Œå¹¶å›žå¤ ACK ç»™å®¢æˆ·ç«¯ï¼ˆåŒæ„释放从客户端到æœåŠ¡å™¨çš„è¿žæŽ¥ï¼‰ï¼›
  3. 客户端收到æœåŠ¡ç«¯å›žå¤çš„ ACK,此时从客户端到æœåŠ¡å™¨çš„è¿žæŽ¥å·²é‡Šæ”¾ï¼ˆä½†æœåŠ¡ç«¯åˆ°å®¢æˆ·ç«¯çš„è¿žæŽ¥è¿˜æœªé‡Šæ”¾ï¼Œå¹¶ä¸”å®¢æˆ·ç«¯è¿˜å¯ä»¥æŽ¥æ”¶æ•°æ®ï¼‰ï¼›
  4. æœåŠ¡ç«¯ç»§ç»­å‘é€ä¹‹å‰æ²¡å‘完的数æ®ç»™å®¢æˆ·ç«¯ï¼›
  5. æœåŠ¡ç«¯å‘é€ FIN+ACK 给客户端,说明æœåŠ¡ç«¯å‘é€å®Œäº†æ•°æ®ï¼ˆè¯·æ±‚释放从æœåŠ¡ç«¯åˆ°å®¢æˆ·ç«¯çš„è¿žæŽ¥ï¼Œå°±ç®—æ²¡æ”¶åˆ°å®¢æˆ·ç«¯çš„å›žå¤ï¼Œè¿‡æ®µæ—¶é—´ä¹Ÿä¼šè‡ªåŠ¨é‡Šæ”¾ï¼‰ï¼›
  6. 客户端收到æœåŠ¡ç«¯çš„ FIN+ACKï¼Œå¹¶å›žå¤ ACK ç»™æœåŠ¡ç«¯ï¼ˆåŒæ„释放从æœåŠ¡ç«¯åˆ°å®¢æˆ·ç«¯çš„è¿žæŽ¥ï¼‰ï¼›
  7. æœåŠ¡ç«¯æ”¶åˆ°å®¢æˆ·ç«¯çš„ ACK åŽï¼Œé‡Šæ”¾ä»ŽæœåŠ¡ç«¯åˆ°å®¢æˆ·ç«¯çš„è¿žæŽ¥ã€‚
TCP 为什么è¦è¿›è¡Œå››æ¬¡æŒ¥æ‰‹ï¼Ÿ

ã€é—®é¢˜ä¸€ã€‘TCP 为什么è¦è¿›è¡Œå››æ¬¡æŒ¥æ‰‹ï¼Ÿ / 为什么 TCP 建立连接需è¦ä¸‰æ¬¡ï¼Œè€Œé‡Šæ”¾è¿žæŽ¥åˆ™éœ€è¦å››æ¬¡ï¼Ÿ

ã€ç­”案一】因为 TCP 是全åŒå·¥æ¨¡å¼ï¼Œå®¢æˆ·ç«¯è¯·æ±‚关闭连接åŽï¼Œå®¢æˆ·ç«¯å‘æœåŠ¡ç«¯çš„è¿žæŽ¥å…³é—­ï¼ˆä¸€äºŒæ¬¡æŒ¥æ‰‹ï¼‰ï¼ŒæœåŠ¡ç«¯ç»§ç»­ä¼ è¾“ä¹‹å‰æ²¡ä¼ å®Œçš„æ•°æ®ç»™å®¢æˆ·ç«¯ï¼ˆæ•°æ®ä¼ è¾“),æœåŠ¡ç«¯å‘客户端的连接关闭(三四次挥手)。所以 TCP 释放连接时æœåŠ¡å™¨çš„ ACK å’Œ FIN 是分开å‘é€çš„ï¼ˆä¸­é—´éš”ç€æ•°æ®ä¼ è¾“),而 TCP 建立连接时æœåŠ¡å™¨çš„ ACK å’Œ SYN 是一起å‘é€çš„ï¼ˆç¬¬äºŒæ¬¡æ¡æ‰‹ï¼‰ï¼Œæ‰€ä»¥ TCP 建立连接需è¦ä¸‰æ¬¡ï¼Œè€Œé‡Šæ”¾è¿žæŽ¥åˆ™éœ€è¦å››æ¬¡ã€‚

ã€é—®é¢˜äºŒã€‘为什么 TCP 连接时å¯ä»¥ ACK å’Œ SYN 一起å‘é€ï¼Œè€Œé‡Šæ”¾æ—¶åˆ™ ACK å’Œ FIN 分开å‘é€å‘¢ï¼Ÿï¼ˆACK å’Œ FIN 分开是指第二次和第三次挥手)

ã€ç­”案二】因为客户端请求释放时,æœåС噍å¯èƒ½è¿˜æœ‰æ•°æ®éœ€è¦ä¼ è¾“给客户端,因此æœåŠ¡ç«¯è¦å…ˆå“应客户端 FIN 请求(æœåŠ¡ç«¯å‘é€ ACKï¼‰ï¼Œç„¶åŽæ•°æ®ä¼ è¾“,传输完æˆåŽï¼ŒæœåŠ¡ç«¯å†æå‡º FIN 请求(æœåŠ¡ç«¯å‘é€ FIN);而连接时则没有中间的数æ®ä¼ è¾“,因此连接时å¯ä»¥ ACK å’Œ SYN 一起å‘é€ã€‚

ã€é—®é¢˜ä¸‰ã€‘为什么客户端释放最åŽéœ€è¦ TIME-WAIT 等待 2MSL 呢?

ã€ç­”案三】

  1. 为了ä¿è¯å®¢æˆ·ç«¯å‘é€çš„æœ€åŽä¸€ä¸ª ACK 报文能够到达æœåŠ¡ç«¯ã€‚è‹¥æœªæˆåŠŸåˆ°è¾¾ï¼Œåˆ™æœåŠ¡ç«¯è¶…æ—¶é‡ä¼  FIN+ACK 报文段,客户端å†é‡ä¼  ACKï¼Œå¹¶é‡æ–°è®¡æ—¶ã€‚
  2. 防止已失效的连接请求报文段出现在本连接中。TIME-WAIT æŒç»­ 2MSL å¯ä½¿æœ¬è¿žæŽ¥æŒç»­çš„æ—¶é—´å†…所产生的所有报文段都从网络中消失,这样å¯ä½¿ä¸‹æ¬¡è¿žæŽ¥ä¸­ä¸ä¼šå‡ºçŽ°æ—§çš„è¿žæŽ¥æŠ¥æ–‡æ®µã€‚

TCP 有é™çŠ¶æ€æœº

TCP 有é™çŠ¶æ€æœºå›¾ç‰‡

TCP 的有é™çŠ¶æ€æœº

应用层

DNS

  • DNS(Domain Name System,域å系统)是互è”网的一项æœåŠ¡ã€‚å®ƒä½œä¸ºå°†åŸŸåå’Œ IP 地å€ç›¸äº’æ˜ å°„çš„ä¸€ä¸ªåˆ†å¸ƒå¼æ•°æ®åº“,能够使人更方便地访问互è”网。DNS 使用 TCP å’Œ UDP ç«¯å£ 53。当å‰ï¼Œå¯¹äºŽæ¯ä¸€çº§åŸŸå长度的é™åˆ¶æ˜¯ 63 ä¸ªå­—ç¬¦ï¼ŒåŸŸåæ€»é•¿åº¦åˆ™ä¸èƒ½è¶…过 253 个字符。

域å:

  • 域å ::= {<三级域å>.<二级域å>.<顶级域å>},如:blog.huihut.com

FTP

  • FTP(File Transfer Protocol,文件传输å议)是用于在网络上进行文件传输的一套标准å议,使用客户/æœåŠ¡å™¨æ¨¡å¼ï¼Œä½¿ç”¨ TCP æ•°æ®æŠ¥ï¼Œæä¾›äº¤äº’å¼è®¿é—®ï¼ŒåŒå‘传输。
  • TFTP(Trivial File Transfer Protocolï¼Œç®€å•æ–‡ä»¶ä¼ è¾“å议)一个å°ä¸”易实现的文件传输å议,也使用客户-æœåŠ¡å™¨æ–¹å¼ï¼Œä½¿ç”¨UDPæ•°æ®æŠ¥ï¼Œåªæ”¯æŒæ–‡ä»¶ä¼ è¾“è€Œä¸æ”¯æŒäº¤äº’,没有列目录,ä¸èƒ½å¯¹ç”¨æˆ·è¿›è¡Œèº«ä»½é‰´å®š

TELNET

  • TELNET å议是 TCP/IP åè®®æ—中的一员,是 Internet 远程登陆æœåŠ¡çš„æ ‡å‡†åè®®å’Œä¸»è¦æ–¹å¼ã€‚它为用户æä¾›äº†åœ¨æœ¬åœ°è®¡ç®—机上完æˆè¿œç¨‹ä¸»æœºå·¥ä½œçš„能力。

  • HTTP(HyperText Transfer Protocol,超文本传输å议)是用于从 WWW(World Wide Web,万维网)æœåŠ¡å™¨ä¼ è¾“è¶…æ–‡æœ¬åˆ°æœ¬åœ°æµè§ˆå™¨çš„ä¼ é€å议。

  • SMTP(Simple Mail Transfer Protocol,简å•邮件传输å议)是一组用于由æºåœ°å€åˆ°ç›®çš„地å€ä¼ é€é‚®ä»¶çš„è§„åˆ™ï¼Œç”±å®ƒæ¥æŽ§åˆ¶ä¿¡ä»¶çš„ä¸­è½¬æ–¹å¼ã€‚SMTP å议属于 TCP/IP å议簇,它帮助æ¯å°è®¡ç®—机在å‘逿ˆ–中转信件时找到下一个目的地。

  • Socket 建立网络通信连接至少è¦ä¸€å¯¹ç«¯å£å·ï¼ˆSocket)。Socket 本质是编程接å£ï¼ˆAPI),对 TCP/IP çš„å°è£…,TCP/IP ä¹Ÿè¦æä¾›å¯ä¾›ç¨‹åºå‘˜åšç½‘ç»œå¼€å‘æ‰€ç”¨çš„æŽ¥å£ï¼Œè¿™å°±æ˜¯ Socket 编程接å£ã€‚

WWW

  • WWW(World Wide Web,环çƒä¿¡æ¯ç½‘,万维网)是一个由许多互相链接的超文本组æˆçš„系统,通过互è”网访问
URL
  • URL(Uniform Resource Locator,统一资æºå®šä½ç¬¦ï¼‰æ˜¯å› ç‰¹ç½‘上标准的资æºçš„地å€ï¼ˆAddress)

标准格å¼ï¼š

  • å议类型:[//æœåŠ¡å™¨åœ°å€[:端å£å·]][/资æºå±‚级UNIX文件路径]文件å[?查询][#片段ID]

完整格å¼ï¼š

  • å议类型:[//[访问资æºéœ€è¦çš„凭è¯ä¿¡æ¯@]æœåŠ¡å™¨åœ°å€[:端å£å·]][/资æºå±‚级UNIX文件路径]文件å[?查询][#片段ID]

其中ã€è®¿é—®å‡­è¯ä¿¡æ¯@ï¼›:端å£å·ï¼›?查询;#片段ID】都属于选填项
如:https://github.com/huihut/interview#cc

HTTP

HTTP(HyperText Transfer Protocol,超文本传输å议)是一ç§ç”¨äºŽåˆ†å¸ƒå¼ã€å作å¼å’Œè¶…媒体信æ¯ç³»ç»Ÿçš„应用层å议。HTTP 是万维网的数æ®é€šä¿¡çš„基础。

请求方法

方法 æ„义
OPTIONS 请求一些选项信æ¯ï¼Œå…许客户端查看æœåŠ¡å™¨çš„æ€§èƒ½
GET 请求指定的页é¢ä¿¡æ¯ï¼Œå¹¶è¿”回实体主体
HEAD 类似于 get 请求,åªä¸è¿‡è¿”回的å“åº”ä¸­æ²¡æœ‰å…·ä½“çš„å†…å®¹ï¼Œç”¨äºŽèŽ·å–æŠ¥å¤´
POST 呿Œ‡å®šèµ„æºæäº¤æ•°æ®è¿›è¡Œå¤„ç†è¯·æ±‚(例如æäº¤è¡¨å•或者上传文件)。数æ®è¢«åŒ…å«åœ¨è¯·æ±‚体中。POST请求å¯èƒ½ä¼šå¯¼è‡´æ–°çš„资æºçš„建立和/或已有资æºçš„修改
PUT ä»Žå®¢æˆ·ç«¯å‘æœåС噍传é€çš„æ•°æ®å–代指定的文档的内容
DELETE 请求æœåŠ¡å™¨åˆ é™¤æŒ‡å®šçš„é¡µé¢
TRACE 回显æœåŠ¡å™¨æ”¶åˆ°çš„è¯·æ±‚ï¼Œä¸»è¦ç”¨äºŽæµ‹è¯•或诊断

状æ€ç ï¼ˆStatus-Code)

  • 1xx:表示通知信æ¯ï¼Œå¦‚请求收到了或正在进行处ç†
    • 100 Continue:继续,客户端应继续其请求
    • 101 Switching Protocols 切æ¢å议。æœåŠ¡å™¨æ ¹æ®å®¢æˆ·ç«¯çš„请求切æ¢å议。åªèƒ½åˆ‡æ¢åˆ°æ›´é«˜çº§çš„å议,例如,切æ¢åˆ° HTTP 的新版本åè®®
  • 2xx:表示æˆåŠŸï¼Œå¦‚æŽ¥æ”¶æˆ–çŸ¥é“了
    • 200 OK: 请求æˆåŠŸ
  • 3xx:表示é‡å®šå‘,如è¦å®Œæˆè¯·æ±‚还必须采å–进一步的行动
    • 301 Moved Permanently: 永久移动。请求的资æºå·²è¢«æ°¸ä¹…的移动到新 URL,返回信æ¯ä¼šåŒ…括新的 URL,æµè§ˆå™¨ä¼šè‡ªåŠ¨å®šå‘到新 URL。今åŽä»»ä½•新的请求都应使用新的 URL 代替
  • 4xx:表示客户的差错,如请求中有错误的语法或ä¸èƒ½å®Œæˆ
    • 400 Bad Request: 客户端请求的语法错误,æœåŠ¡å™¨æ— æ³•ç†è§£
    • 401 Unauthorized: è¯·æ±‚è¦æ±‚用户的身份认è¯
    • 403 Forbidden: æœåС噍ç†è§£è¯·æ±‚å®¢æˆ·ç«¯çš„è¯·æ±‚ï¼Œä½†æ˜¯æ‹’ç»æ‰§è¡Œæ­¤è¯·æ±‚(æƒé™ä¸å¤Ÿï¼‰
    • 404 Not Found: æœåŠ¡å™¨æ— æ³•æ ¹æ®å®¢æˆ·ç«¯çš„请求找到资æºï¼ˆç½‘页)。通过此代ç ï¼Œç½‘站设计人员å¯è®¾ç½® â€œæ‚¨æ‰€è¯·æ±‚çš„èµ„æºæ— æ³•找到†的个性页é¢
    • 408 Request Timeout: æœåŠ¡å™¨ç­‰å¾…å®¢æˆ·ç«¯å‘é€çš„请求时间过长,超时
  • 5xx:表示æœåŠ¡å™¨çš„å·®é”™ï¼Œå¦‚æœåŠ¡å™¨å¤±æ•ˆæ— æ³•å®Œæˆè¯·æ±‚
    • 500 Internal Server Error: æœåŠ¡å™¨å†…éƒ¨é”™è¯¯ï¼Œæ— æ³•å®Œæˆè¯·æ±‚
    • 503 Service Unavailable: 由于超载或系统维护,æœåŠ¡å™¨æš‚æ—¶çš„æ— æ³•å¤„ç†å®¢æˆ·ç«¯çš„请求。延时的长度å¯åŒ…å«åœ¨æœåŠ¡å™¨çš„ Retry-After 头信æ¯ä¸­
    • 504 Gateway Timeout: 充当网关或代ç†çš„æœåŠ¡å™¨ï¼ŒæœªåŠæ—¶ä»Žè¿œç«¯æœåŠ¡å™¨èŽ·å–请求

更多状æ€ç ï¼šèœé¸Ÿæ•™ç¨‹ . HTTP状æ€ç 

å…¶ä»–åè®®
  • SMTP(Simple Main Transfer Protocol,简å•邮件传输å议)是在 Internet 传输 Email 的标准,是一个相对简å•的基于文本的åè®®ã€‚åœ¨å…¶ä¹‹ä¸ŠæŒ‡å®šäº†ä¸€æ¡æ¶ˆæ¯çš„ä¸€ä¸ªæˆ–å¤šä¸ªæŽ¥æ”¶è€…ï¼ˆåœ¨å¤§å¤šæ•°æƒ…å†µä¸‹è¢«ç¡®è®¤æ˜¯å­˜åœ¨çš„ï¼‰ï¼Œç„¶åŽæ¶ˆæ¯æ–‡æœ¬ä¼šè¢«ä¼ è¾“。å¯ä»¥å¾ˆç®€å•地通过 Telnet ç¨‹åºæ¥æµ‹è¯•一个 SMTP æœåŠ¡å™¨ã€‚SMTP 使用 TCP ç«¯å£ 25。
  • DHCP(Dynamic Host Configuration Protocol,动æ€ä¸»æœºè®¾ç½®å议)是一个局域网的网络å议,使用 UDP åè®®å·¥ä½œï¼Œä¸»è¦æœ‰ä¸¤ä¸ªç”¨é€”:
    • 用于内部网络或网络æœåŠ¡ä¾›åº”å•†è‡ªåŠ¨åˆ†é… IP 地å€ç»™ç”¨æˆ·
    • 用于内部网络管ç†å‘˜ä½œä¸ºå¯¹æ‰€æœ‰ç”µè„‘作中央管ç†çš„æ‰‹æ®µ
  • SNMP(Simple Network Management Protocol,简å•网络管ç†å议)构æˆäº†äº’è”网工程工作å°ç»„(IETF,Internet Engineering Task Force)定义的 Internet åè®®æ—的一部分。该å议能够支æŒç½‘络管ç†ç³»ç»Ÿï¼Œç”¨ä»¥ç›‘æµ‹è¿žæŽ¥åˆ°ç½‘ç»œä¸Šçš„è®¾å¤‡æ˜¯å¦æœ‰ä»»ä½•引起管ç†ä¸Šå…³æ³¨çš„æƒ…况。

🌩 网络编程

Socket

Linux Socket 编程(ä¸é™ Linux)

Socket 客户端æœåŠ¡å™¨é€šè®¯

Socket 中的 read()ã€write() 函数

ssize_t read(int fd, void *buf, size_t count);
ssize_t write(int fd, const void *buf, size_t count);
read()
  • read 函数是负责从 fd 中读å–内容。
  • 当读æˆåŠŸæ—¶ï¼Œread 返回实际所读的字节数。
  • 如果返回的值是 0 表示已ç»è¯»åˆ°æ–‡ä»¶çš„结æŸäº†ï¼Œå°äºŽ 0 表示出现了错误。
  • 如果错误为 EINTR 说明读是由中断引起的;如果是 ECONNREST 表示网络连接出了问题。
write()
  • write 函数将 buf 中的 nbytes 字节内容写入文件æè¿°ç¬¦ fd。
  • æˆåŠŸæ—¶è¿”å›žå†™çš„å­—èŠ‚æ•°ã€‚å¤±è´¥æ—¶è¿”å›ž -1,并设置 errno å˜é‡ã€‚
  • 在网络程åºä¸­ï¼Œå½“我们å‘套接字文件æè¿°ç¬¦å†™æ—¶æœ‰ä¿©ç§å¯èƒ½ã€‚
  • (1)write 的返回值大于 0,表示写了部分或者是全部的数æ®ã€‚
  • (2)返回的值å°äºŽ 0,此时出现了错误。
  • 如果错误为 EINTR 表示在写的时候出现了中断错误;如果为 EPIPE 表示网络连接出现了问题(对方已ç»å…³é—­äº†è¿žæŽ¥ï¼‰ã€‚

Socket 中 TCP çš„ä¸‰æ¬¡æ¡æ‰‹å»ºç«‹è¿žæŽ¥

æˆ‘ä»¬çŸ¥é“ TCP 建立连接è¦è¿›è¡Œ â€œä¸‰æ¬¡æ¡æ‰‹â€ï¼Œå³äº¤æ¢ä¸‰ä¸ªåˆ†ç»„。大致æµç¨‹å¦‚下:

  1. å®¢æˆ·ç«¯å‘æœåС噍å‘é€ä¸€ä¸ª SYN J
  2. æœåС噍å‘客户端å“应一个 SYN K,并对 SYN J 进行确认 ACK J+1
  3. å®¢æˆ·ç«¯å†æƒ³æœåС噍å‘一个确认 ACK K+1

åªæœ‰å°±å®Œäº†ä¸‰æ¬¡æ¡æ‰‹ï¼Œä½†æ˜¯è¿™ä¸ªä¸‰æ¬¡æ¡æ‰‹å‘生在 Socket 的那几个函数中呢?请看下图:

socket 中å‘é€çš„ TCP ä¸‰æ¬¡æ¡æ‰‹

从图中å¯ä»¥çœ‹å‡ºï¼š

  1. 当客户端调用 connect 时,触å‘äº†è¿žæŽ¥è¯·æ±‚ï¼Œå‘æœåС噍å‘é€äº† SYN J 包,这时 connect 进入阻塞状æ€ï¼›
  2. æœåŠ¡å™¨ç›‘å¬åˆ°è¿žæŽ¥è¯·æ±‚ï¼Œå³æ”¶åˆ° SYN J 包,调用 accept 函数接收请求å‘客户端å‘é€ SYN K ,ACK J+1,这时 accept 进入阻塞状æ€ï¼›
  3. 客户端收到æœåŠ¡å™¨çš„ SYN K ,ACK J+1 之åŽï¼Œè¿™æ—¶ connect 返回,并对 SYN K 进行确认;
  4. æœåŠ¡å™¨æ”¶åˆ° ACK K+1 时,accept è¿”å›žï¼Œè‡³æ­¤ä¸‰æ¬¡æ¡æ‰‹å®Œæ¯•,连接建立。

Socket 中 TCP çš„å››æ¬¡æ¡æ‰‹é‡Šæ”¾è¿žæŽ¥

上é¢ä»‹ç»äº† socket 中 TCP çš„ä¸‰æ¬¡æ¡æ‰‹å»ºç«‹è¿‡ç¨‹ï¼ŒåŠå…¶æ¶‰åŠçš„ socket å‡½æ•°ã€‚çŽ°åœ¨æˆ‘ä»¬ä»‹ç» socket ä¸­çš„å››æ¬¡æ¡æ‰‹é‡Šæ”¾è¿žæŽ¥çš„过程,请看下图:

socket 中å‘é€çš„ TCP å››æ¬¡æ¡æ‰‹

图示过程如下:

  1. æŸä¸ªåº”用进程首先调用 close 主动关闭连接,这时 TCP å‘é€ä¸€ä¸ª FIN Mï¼›
  2. å¦ä¸€ç«¯æŽ¥æ”¶åˆ° FIN M 之åŽï¼Œæ‰§è¡Œè¢«åŠ¨å…³é—­ï¼Œå¯¹è¿™ä¸ª FIN 进行确认。它的接收也作为文件结æŸç¬¦ä¼ é€’给应用进程,因为 FIN 的接收æ„味ç€åº”用进程在相应的连接上å†ä¹ŸæŽ¥æ”¶ä¸åˆ°é¢å¤–æ•°æ®ï¼›
  3. 一段时间之åŽï¼ŒæŽ¥æ”¶åˆ°æ–‡ä»¶ç»“æŸç¬¦çš„应用进程调用 close 关闭它的 socket。这导致它的 TCP 也å‘é€ä¸€ä¸ª FIN Nï¼›
  4. 接收到这个 FIN çš„æºå‘é€ç«¯ TCP 对它进行确认。

这样æ¯ä¸ªæ–¹å‘上都有一个 FIN å’Œ ACK。

💾 æ•°æ®åº“

本节部分知识点æ¥è‡ªã€Šæ•°æ®åº“系统概论(第 5 版)》

基本概念

  • æ•°æ®ï¼ˆdata):æè¿°äº‹ç‰©çš„符å·è®°å½•称为数æ®ã€‚
  • æ•°æ®åº“(DataBase,DBï¼‰ï¼šæ˜¯é•¿æœŸå­˜å‚¨åœ¨è®¡ç®—æœºå†…ã€æœ‰ç»„织的ã€å¯å…±äº«çš„大釿•°æ®çš„集åˆï¼Œå…·æœ‰æ°¸ä¹…å­˜å‚¨ã€æœ‰ç»„织ã€å¯å…±äº«ä¸‰ä¸ªåŸºæœ¬ç‰¹ç‚¹ã€‚
  • æ•°æ®åº“管ç†ç³»ç»Ÿï¼ˆDataBase Management System,DBMS):是ä½äºŽç”¨æˆ·ä¸Žæ“作系统之间的一层数æ®ç®¡ç†è½¯ä»¶ã€‚
  • æ•°æ®åº“系统(DataBase System,DBS):是有数æ®åº“ã€æ•°æ®åº“管ç†ç³»ç»Ÿï¼ˆåŠå…¶åº”用开å‘工具)ã€åº”用程åºå’Œæ•°æ®åº“管ç†å‘˜ï¼ˆDataBase Administrator DBA)组æˆçš„存储ã€ç®¡ç†ã€å¤„ç†å’Œç»´æŠ¤æ•°æ®çš„系统。
  • 实体(entity):客观存在并å¯ç›¸äº’区别的事物称为实体。
  • 属性(attribute):实体所具有的æŸä¸€ç‰¹æ€§ç§°ä¸ºå±žæ€§ã€‚
  • ç ï¼ˆkey):唯一标识实体的属性集称为ç ã€‚
  • 实体型(entity type):用实体ååŠå…¶å±žæ€§åé›†åˆæ¥æŠ½è±¡å’Œåˆ»ç”»åŒç±»å®žä½“,称为实体型。
  • 实体集(entity set):åŒä¸€å®žä½“型的集åˆç§°ä¸ºå®žä½“集。
  • è”系(relationship):实体之间的è”系通常是指ä¸åŒå®žä½“集之间的è”系。
  • 模å¼ï¼ˆschema):模å¼ä¹Ÿç§°é€»è¾‘模å¼ï¼Œæ˜¯æ•°æ®åº“全体数æ®çš„逻辑结构和特å¾çš„æè¿°ï¼Œæ˜¯æ‰€æœ‰ç”¨æˆ·çš„公共数æ®è§†å›¾ã€‚
  • 外模å¼ï¼ˆexternal schema):外模å¼ä¹Ÿç§°å­æ¨¡å¼ï¼ˆsubschema)或用户模å¼ï¼Œå®ƒæ˜¯æ•°æ®åº“用户(包括应用程åºå‘˜å’Œæœ€ç»ˆç”¨æˆ·ï¼‰èƒ½å¤Ÿçœ‹è§å’Œä½¿ç”¨çš„局部数æ®çš„逻辑结构和特å¾çš„æè¿°ï¼Œæ˜¯æ•°æ®åº“用户的数æ®è§†å›¾ï¼Œæ˜¯ä¸ŽæŸä¸€åº”用有关的数æ®çš„逻辑表示。
  • 内模å¼ï¼ˆinternal schema):内模å¼ä¹Ÿç§°ä¸ºå­˜å‚¨æ¨¡å¼ï¼ˆstorage schema),一个数æ®åº“åªæœ‰ä¸€ä¸ªå†…模å¼ã€‚他是数æ®ç‰©ç†ç»“构和存储方å¼çš„æè¿°ï¼Œæ˜¯æ•°æ®åº“在数æ®åº“内部的组织方å¼ã€‚

å¸¸ç”¨æ•°æ®æ¨¡åž‹

  • 层次模型(hierarchical model)
  • 网状模型(network model)
  • 关系模型(relational model)
    • 关系(relation):一个关系对应通常说的一张表
    • 元组(tuple):表中的一行å³ä¸ºä¸€ä¸ªå…ƒç»„
    • 属性(attribute):表中的一列å³ä¸ºä¸€ä¸ªå±žæ€§
    • ç ï¼ˆkey):表中å¯ä»¥å”¯ä¸€ç¡®å®šä¸€ä¸ªå…ƒç»„çš„æŸä¸ªå±žæ€§ç»„
    • 域(domainï¼‰ï¼šä¸€ç»„å…·æœ‰ç›¸åŒæ•°æ®ç±»åž‹çš„值的集åˆ
    • 分é‡ï¼šå…ƒç»„中的一个属性值
    • 关系模å¼ï¼šå¯¹å…³ç³»çš„æè¿°ï¼Œä¸€èˆ¬è¡¨ç¤ºä¸º 关系å(属性1, 属性2, ..., 属性n)
  • é¢å‘å¯¹è±¡æ•°æ®æ¨¡åž‹ï¼ˆobject oriented data model)
  • å¯¹è±¡å…³ç³»æ•°æ®æ¨¡åž‹ï¼ˆobject relational data model)
  • åŠç»“æž„åŒ–æ•°æ®æ¨¡åž‹ï¼ˆsemistructure data model)

常用 SQL æ“作

对象类型 对象 æ“作类型
æ•°æ®åº“æ¨¡å¼ æ¨¡å¼ CREATE SCHEMA
基本表 CREATE SCHEMA,ALTER TABLE
视图 CREATE VIEW
索引 CREATE INDEX
æ•°æ® åŸºæœ¬è¡¨å’Œè§†å›¾ SELECT,INSERT,UPDATE,DELETE,REFERENCES,ALL PRIVILEGES
属性列 SELECT,INSERT,UPDATE,REFERENCES,ALL PRIVILEGES

SQL 语法教程:runoob . SQL 教程

关系型数æ®åº“

  • 基本关系æ“ä½œï¼šæŸ¥è¯¢ï¼ˆé€‰æ‹©ã€æŠ•å½±ã€è¿žæŽ¥ï¼ˆç­‰å€¼è¿žæŽ¥ã€è‡ªç„¶è¿žæŽ¥ã€å¤–连接(左外连接ã€å³å¤–连接))ã€é™¤ã€å¹¶ã€å·®ã€äº¤ã€ç¬›å¡å°”ç§¯ç­‰ï¼‰ã€æ’å…¥ã€åˆ é™¤ã€ä¿®æ”¹
  • 关系模型中的三类完整性约æŸï¼šå®žä½“完整性ã€å‚照完整性ã€ç”¨æˆ·å®šä¹‰çš„完整性

索引

æ•°æ®åº“完整性

  • æ•°æ®åº“的完整性是指数æ®çš„æ­£ç¡®æ€§å’Œç›¸å®¹æ€§ã€‚
    • 完整性:为了防止数æ®åº“中存在ä¸ç¬¦åˆè¯­ä¹‰ï¼ˆä¸æ­£ç¡®ï¼‰çš„æ•°æ®ã€‚
    • å®‰å…¨æ€§ï¼šä¸ºäº†ä¿æŠ¤æ•°æ®åº“é˜²æ­¢æ¶æ„ç ´åå’Œéžæ³•å­˜å–。
  • 触å‘器:是用户定义在关系表中的一类由事件驱动的特殊过程。

关系数æ®ç†è®º

  • æ•°æ®ä¾èµ–是一个关系内部属性与属性之间的一ç§çº¦æŸå…³ç³»ï¼Œæ˜¯é€šè¿‡å±žæ€§é—´å€¼çš„相等与å¦ä½“现出æ¥çš„æ•°æ®é—´ç›¸å…³è”系。
  • 最é‡è¦çš„æ•°æ®ä¾èµ–:函数ä¾èµ–ã€å¤šå€¼ä¾èµ–。

范å¼

  • 第一范å¼ï¼ˆ1NF):属性(字段)是最å°å•ä½ä¸å¯å†åˆ†ã€‚
  • 第二范å¼ï¼ˆ2NF):满足 1NF,æ¯ä¸ªéžä¸»å±žæ€§å®Œå…¨ä¾èµ–于主键(消除 1NF éžä¸»å±žæ€§å¯¹ç çš„部分函数ä¾èµ–)。
  • 第三范å¼ï¼ˆ3NF):满足 2NF,任何éžä¸»å±žæ€§ä¸ä¾èµ–于其他éžä¸»å±žæ€§ï¼ˆæ¶ˆé™¤ 2NF éžä¸»å±žæ€§å¯¹ç çš„传递函数ä¾èµ–)。
  • é²ä¾æ–¯-科得范å¼ï¼ˆBCNF):满足 3NF,任何éžä¸»å±žæ€§ä¸èƒ½å¯¹ä¸»é”®å­é›†ä¾èµ–(消除 3NF 主属性对ç çš„部分和传递函数ä¾èµ–)。
  • 第四范å¼ï¼ˆ4NF):满足 3NF,属性之间ä¸èƒ½æœ‰éžå¹³å‡¡ä¸”éžå‡½æ•°ä¾èµ–的多值ä¾èµ–(消除 3NF éžå¹³å‡¡ä¸”éžå‡½æ•°ä¾èµ–的多值ä¾èµ–)。

æ•°æ®åº“æ¢å¤

  • 事务:是用户定义的一个数æ®åº“æ“作åºåˆ—,这些æ“作è¦ä¹ˆå…¨åšï¼Œè¦ä¹ˆå…¨ä¸åšï¼Œæ˜¯ä¸€ä¸ªä¸å¯åˆ†å‰²çš„工作å•ä½ã€‚
  • 事物的 ACID ç‰¹æ€§ï¼šåŽŸå­æ€§ã€ä¸€è‡´æ€§ã€éš”ç¦»æ€§ã€æŒç»­æ€§ã€‚
  • æ¢å¤çš„å®žçŽ°æŠ€æœ¯ï¼šå»ºç«‹å†—ä½™æ•°æ® -> 利用冗余数æ®å®žæ–½æ•°æ®åº“æ¢å¤ã€‚
  • 建立冗余数æ®å¸¸ç”¨æŠ€æœ¯ï¼šæ•°æ®è½¬å‚¨ï¼ˆåŠ¨æ€æµ·é‡è½¬å‚¨ã€åЍæ€å¢žé‡è½¬å‚¨ã€é™æ€æµ·é‡è½¬å‚¨ã€é™æ€å¢žé‡è½¬å‚¨ï¼‰ã€ç™»è®°æ—¥å¿—文件。

å¹¶å‘æŽ§åˆ¶

  • äº‹åŠ¡æ˜¯å¹¶å‘æŽ§åˆ¶çš„åŸºæœ¬å•ä½ã€‚
  • 并呿“作带æ¥çš„æ•°æ®ä¸ä¸€è‡´æ€§åŒ…括:丢失修改ã€ä¸å¯é‡å¤è¯»ã€è¯» “脆数æ®ã€‚
  • å¹¶å‘æŽ§åˆ¶ä¸»è¦æŠ€æœ¯ï¼šå°é”ã€æ—¶é—´æˆ³ã€ä¹è§‚控制法ã€å¤šç‰ˆæœ¬å¹¶å‘控制等。
  • 基本å°é”类型:排他é”(X é” / 写é”)ã€å…±äº«é”(S é” / 读é”)。
  • æ´»é”æ­»é”:
    • æ´»é”:事务永远处于等待状æ€ï¼Œå¯é€šè¿‡å…ˆæ¥å…ˆæœåŠ¡çš„ç­–ç•¥é¿å…。
    • æ­»é”:事务永远ä¸èƒ½ç»“æŸ
      • 预防:一次å°é”法ã€é¡ºåºå°é”法;
      • 诊断:超时法ã€ç­‰å¾…图法;
      • è§£é™¤ï¼šæ’¤é”€å¤„ç†æ­»é”代价最å°çš„事务,并释放此事务的所有的é”,使其他事务得以继续è¿è¡Œä¸‹åŽ»ã€‚
  • å¯ä¸²è¡ŒåŒ–è°ƒåº¦ï¼šå¤šä¸ªäº‹åŠ¡çš„å¹¶å‘æ‰§è¡Œæ˜¯æ­£ç¡®çš„,当且仅当其结果与按æŸä¸€æ¬¡åºä¸²è¡Œåœ°æ‰§è¡Œè¿™äº›äº‹åŠ¡æ—¶çš„ç»“æžœç›¸åŒã€‚å¯ä¸²è¡Œæ€§æ—¶å¹¶å‘事务正确调度的准则。

📠设计模å¼

å„大设计模å¼ä¾‹å­å‚考:CSDNä¸“æ  . C++ è®¾è®¡æ¨¡å¼ ç³»åˆ—åšæ–‡

设计模å¼å·¥ç¨‹ç›®å½•

å•例模å¼

å•例模å¼ä¾‹å­

抽象工厂模å¼

抽象工厂模å¼ä¾‹å­

适é…器模å¼

适é…器模å¼ä¾‹å­

桥接模å¼

桥接模å¼ä¾‹å­

观察者模å¼

观察者模å¼ä¾‹å­

设计模å¼çš„六大原则

  • å•一èŒè´£åŽŸåˆ™ï¼ˆSRP,Single Responsibility Principle)
  • é‡Œæ°æ›¿æ¢åŽŸåˆ™ï¼ˆLSP,Liskov Substitution Principle)
  • ä¾èµ–倒置原则(DIP,Dependence Inversion Principle)
  • 接å£éš”离原则(ISP,Interface Segregation Principle)
  • 迪米特法则(LoD,Law of Demeter)
  • 开放å°é—­åŽŸåˆ™ï¼ˆOCP,Open Close Principle)

âš™ï¸ é“¾æŽ¥è£…è½½åº“

本节部分知识点æ¥è‡ªã€Šç¨‹åºå‘˜çš„自我修养——链接装载库》

å†…å­˜ã€æ ˆã€å †

一般应用程åºå†…存空间有如下区域:

  • 栈:由æ“作系统自动分é…é‡Šæ”¾ï¼Œå­˜æ”¾å‡½æ•°çš„å‚æ•°å€¼ã€å±€éƒ¨å˜é‡ç­‰çš„值,用于维护函数调用的上下文
  • 堆:一般由程åºå‘˜åˆ†é…释放,若程åºå‘˜ä¸é‡Šæ”¾ï¼Œç¨‹åºç»“æŸæ—¶å¯èƒ½ç”±æ“作系统回收,用æ¥å®¹çº³åº”用程åºåЍæ€åˆ†é…的内存区域
  • 坿‰§è¡Œæ–‡ä»¶æ˜ åƒï¼šå­˜å‚¨ç€å¯æ‰§è¡Œæ–‡ä»¶åœ¨å†…存中的映åƒï¼Œç”±è£…è½½å™¨è£…è½½æ˜¯å°†å¯æ‰§è¡Œæ–‡ä»¶çš„å†…å­˜è¯»å–æˆ–映射到这里
  • ä¿ç•™åŒºï¼šä¿ç•™åŒºå¹¶ä¸æ˜¯ä¸€ä¸ªå•一的内存区域,而是对内存中å—åˆ°ä¿æŠ¤è€Œç¦æ­¢è®¿é—®çš„内存区域的总称,如通常 C 语言讲无效指针赋值为 0(NULL),因此 0 åœ°å€æ­£å¸¸æƒ…况下ä¸å¯èƒ½æœ‰æ•ˆçš„访问数æ®

æ ˆ

æ ˆä¿å­˜äº†ä¸€ä¸ªå‡½æ•°è°ƒç”¨æ‰€éœ€è¦çš„维护信æ¯ï¼Œå¸¸è¢«ç§°ä¸ºå †æ ˆå¸§ï¼ˆStack Frame)或活动记录(Activate Record),一般包å«ä»¥ä¸‹å‡ æ–¹é¢ï¼š

  • 函数的返回地å€å’Œå‚æ•°
  • 临时å˜é‡ï¼šåŒ…括函数的éžé™æ€å±€éƒ¨å˜é‡ä»¥åŠç¼–译器自动生æˆçš„其他临时å˜é‡
  • ä¿å­˜ä¸Šä¸‹æ–‡ï¼šåŒ…括函数调用å‰åŽéœ€è¦ä¿æŒä¸å˜çš„寄存器

å †

堆分é…算法:

  • 空闲链表(Free List)
  • ä½å›¾ï¼ˆBitmap)
  • 对象池

“段错误(segment fault)†或 â€œéžæ³•æ“作,该内存地å€ä¸èƒ½ read/writeâ€

å…¸åž‹çš„éžæ³•指针解引用造æˆçš„错误。当指针指å‘一个ä¸å…许读写的内存地å€ï¼Œè€Œç¨‹åºå´è¯•图利用指针æ¥è¯»æˆ–å†™è¯¥åœ°å€æ—¶ï¼Œä¼šå‡ºçŽ°è¿™ä¸ªé”™è¯¯ã€‚

æ™®é原因:

  • 将指针åˆå§‹åŒ–为 NULLï¼Œä¹‹åŽæ²¡æœ‰ç»™å®ƒä¸€ä¸ªåˆç†çš„值就开始使用指针
  • 没用åˆå§‹åŒ–æ ˆä¸­çš„æŒ‡é’ˆï¼ŒæŒ‡é’ˆçš„å€¼ä¸€èˆ¬ä¼šæ˜¯éšæœºæ•°ï¼Œä¹‹åŽå°±ç›´æŽ¥å¼€å§‹ä½¿ç”¨æŒ‡é’ˆ

编译链接

å„平尿–‡ä»¶æ ¼å¼

å¹³å° å¯æ‰§è¡Œæ–‡ä»¶ 目标文件 动æ€åº“/共享对象 陿€åº“
Windows exe obj dll lib
Unix/Linux ELFã€out o so a
Mac Mach-O o dylibã€tbdã€framework aã€framework

编译链接过程

  1. 预编译(预编译器处ç†å¦‚ #includeã€#define ç­‰é¢„ç¼–è¯‘æŒ‡ä»¤ï¼Œç”Ÿæˆ .i 或 .ii 文件)
  2. ç¼–è¯‘ï¼ˆç¼–è¯‘å™¨è¿›è¡Œè¯æ³•分æžã€è¯­æ³•分æžã€è¯­ä¹‰åˆ†æžã€ä¸­é—´ä»£ç ç”Ÿæˆã€ç›®æ ‡ä»£ç ç”Ÿæˆã€ä¼˜åŒ–ï¼Œç”Ÿæˆ .s 文件)
  3. 汇编(汇编器把汇编ç ç¿»è¯‘æˆæœºå™¨ç ï¼Œç”Ÿæˆ .o 文件)
  4. 链接(连接器进行地å€å’Œç©ºé—´åˆ†é…ã€ç¬¦å·å†³è®®ã€é‡å®šä½ï¼Œç”Ÿæˆ .out 文件)

现在版本 GCC æŠŠé¢„ç¼–è¯‘å’Œç¼–è¯‘åˆæˆä¸€æ­¥ï¼Œé¢„ç¼–è¯‘ç¼–è¯‘ç¨‹åº cc1ã€æ±‡ç¼–器 asã€è¿žæŽ¥å™¨ ld

MSVC 编译环境,编译器 clã€è¿žæŽ¥å™¨ linkã€å¯æ‰§è¡Œæ–‡ä»¶æŸ¥çœ‹å™¨ dumpbin

目标文件

编译器编译æºä»£ç åŽç”Ÿæˆçš„æ–‡ä»¶å«åšç›®æ ‡æ–‡ä»¶ã€‚目标文件从结构上讲,它是已ç»ç¼–译åŽçš„坿‰§è¡Œæ–‡ä»¶æ ¼å¼ï¼Œåªæ˜¯è¿˜æ²¡æœ‰ç»è¿‡é“¾æŽ¥çš„过程,其中å¯èƒ½æœ‰äº›ç¬¦å·æˆ–有些地å€è¿˜æ²¡æœ‰è¢«è°ƒæ•´ã€‚

坿‰§è¡Œæ–‡ä»¶ï¼ˆWindows çš„ .exe å’Œ Linux çš„ ELF)ã€åЍæ€é“¾æŽ¥åº“(Windows çš„ .dll å’Œ Linux çš„ .so)ã€é™æ€é“¾æŽ¥åº“(Windows çš„ .lib å’Œ Linux çš„ .aï¼‰éƒ½æ˜¯æŒ‰ç…§å¯æ‰§è¡Œæ–‡ä»¶æ ¼å¼å­˜å‚¨ï¼ˆWindows 按照 PE-COFF,Linux 按照 ELF)

目标文件格å¼
  • Windows çš„ PE(Portable Executable),或称为 PE-COFF,.obj æ ¼å¼
  • Linux çš„ ELF(Executable Linkable Format),.o æ ¼å¼
  • Intel/Microsoft çš„ OMF(Object Module Format)
  • Unix çš„ a.out æ ¼å¼
  • MS-DOS çš„ .COM æ ¼å¼

PE å’Œ ELF 都是 COFF(Common File Format)的å˜ç§

目标文件存储结构
段 功能
File Header 文件头,æè¿°æ•´ä¸ªæ–‡ä»¶çš„æ–‡ä»¶å±žæ€§ï¼ˆåŒ…括文件是å¦å¯æ‰§è¡Œã€æ˜¯é™æ€é“¾æŽ¥æˆ–动æ€è¿žæŽ¥åŠå…¥å£åœ°å€ã€ç›®æ ‡ç¡¬ä»¶ã€ç›®æ ‡æ“作系统等)
.text section ä»£ç æ®µï¼Œæ‰§è¡Œè¯­å¥ç¼–译æˆçš„æœºå™¨ä»£ç 
.data section æ•°æ®æ®µï¼Œå·²åˆå§‹åŒ–的全局å˜é‡å’Œå±€éƒ¨é™æ€å˜é‡
.bss section BSS 段(Block Started by Symbol),未åˆå§‹åŒ–的全局å˜é‡å’Œå±€éƒ¨é™æ€å˜é‡ï¼ˆå› ä¸ºé»˜è®¤å€¼ä¸º 0ï¼Œæ‰€ä»¥åªæ˜¯åœ¨æ­¤é¢„ç•™ä½ç½®ï¼Œä¸å ç©ºé—´ï¼‰
.rodata section åªè¯»æ•°æ®æ®µï¼Œå­˜æ”¾åªè¯»æ•°æ®ï¼Œä¸€èˆ¬æ˜¯ç¨‹åºé‡Œé¢çš„åªè¯»å˜é‡ï¼ˆå¦‚ const 修饰的å˜é‡ï¼‰å’Œå­—符串常é‡
.comment section æ³¨é‡Šä¿¡æ¯æ®µï¼Œå­˜æ”¾ç¼–译器版本信æ¯
.note.GNU-stack section 堆栈æç¤ºæ®µ

其他段略

链接的接å£â€”———符å·

在链接中,目标文件之间相互拼åˆå®žé™…上是目标文件之间对地å€çš„引用,å³å¯¹å‡½æ•°å’Œå˜é‡çš„地å€çš„引用。我们将函数和å˜é‡ç»Ÿç§°ä¸ºç¬¦å·ï¼ˆSymbolï¼‰ï¼Œå‡½æ•°åæˆ–å˜é‡å就是符å·å(Symbol Name)。

如下符å·è¡¨ï¼ˆSymbol Table):

Symbol(符å·å) Symbol Value (地å€ï¼‰
main 0x100
Add 0x123
... ...

Linux 的共享库(Shared Library)

Linux 下的共享库就是普通的 ELF 共享对象。

共享库版本更新应该ä¿è¯äºŒè¿›åˆ¶æŽ¥å£ ABI(Application Binary Interface)的兼容

命å

libname.so.x.y.z

  • x:主版本å·ï¼Œä¸åŒä¸»ç‰ˆæœ¬å·çš„库之间ä¸å…¼å®¹ï¼Œéœ€è¦é‡æ–°ç¼–译
  • y:次版本å·ï¼Œé«˜ç‰ˆæœ¬å·å‘åŽå…¼å®¹ä½Žç‰ˆæœ¬å·
  • z:å‘布版本å·ï¼Œä¸å¯¹æŽ¥å£è¿›è¡Œæ›´æ”¹ï¼Œå®Œå…¨å…¼å®¹

路径

大部分包括 Linux 在内的开æºç³»ç»Ÿéµå¾ª FHS(File Hierarchy Standard)的标准,这标准规定了系统文件如何存放,包括å„个目录结构ã€ç»„织和作用。

  • /lib:存放系统最关键和最基础的共享库,如动æ€é“¾æŽ¥å™¨ã€C 语言è¿è¡Œåº“ã€æ•°å­¦åº“ç­‰
  • /usr/lib:存放éžç³»ç»Ÿè¿è¡Œæ—¶æ‰€éœ€è¦çš„å…³é”®æ€§çš„åº“ï¼Œä¸»è¦æ˜¯å¼€å‘库
  • /usr/local/lib:存放跟æ“作系统本身并ä¸ååˆ†ç›¸å…³çš„åº“ï¼Œä¸»è¦æ˜¯ä¸€äº›ç¬¬ä¸‰æ–¹åº”用程åºçš„库

动æ€é“¾æŽ¥å™¨ä¼šåœ¨ /libã€/usr/lib 和由 /etc/ld.so.conf é…置文件指定的,目录中查找共享库

环境å˜é‡

  • LD_LIBRARY_PATHï¼šä¸´æ—¶æ”¹å˜æŸä¸ªåº”用程åºçš„共享库查找路径,而ä¸ä¼šå½±å“其他应用程åº
  • LD_PRELOAD:指定预先装载的一些共享库甚至是目标文件
  • LD_DEBUG:打开动æ€é“¾æŽ¥å™¨çš„调试功能

so 共享库的编写

使用 CLion 编写共享库

创建一个å为 MySharedLib 的共享库

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(MySharedLib)

set(CMAKE_CXX_STANDARD 11)

add_library(MySharedLib SHARED library.cpp library.h)

library.h

#ifndef MYSHAREDLIB_LIBRARY_H
#define MYSHAREDLIB_LIBRARY_H

// æ‰“å° Hello World!
void hello();

// 使用å¯å˜æ¨¡ç‰ˆå‚数求和
template <typename T>
T sum(T t)
{
    return t;
}
template <typename T, typename ...Types>
T sum(T first, Types ... rest)
{
    return first + sum<T>(rest...);
}

#endif

library.cpp

#include <iostream>
#include "library.h"

void hello() {
    std::cout << "Hello, World!" << std::endl;
}

so å…±äº«åº“çš„ä½¿ç”¨ï¼ˆè¢«å¯æ‰§è¡Œé¡¹ç›®è°ƒç”¨ï¼‰

使用 CLion 调用共享库

创建一个å为 TestSharedLib çš„å¯æ‰§è¡Œé¡¹ç›®

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(TestSharedLib)

# C++11 编译
set(CMAKE_CXX_STANDARD 11)

# 头文件路径
set(INC_DIR /home/xx/code/clion/MySharedLib)
# 库文件路径
set(LIB_DIR /home/xx/code/clion/MySharedLib/cmake-build-debug)

include_directories(${INC_DIR})
link_directories(${LIB_DIR})
link_libraries(MySharedLib)

add_executable(TestSharedLib main.cpp)

# 链接 MySharedLib 库
target_link_libraries(TestSharedLib MySharedLib)

main.cpp

#include <iostream>
#include "library.h"
using std::cout;
using std::endl;

int main() {

    hello();
    cout << "1 + 2 = " << sum(1,2) << endl;
    cout << "1 + 2 + 3 = " << sum(1,2,3) << endl;

    return 0;
}

执行结果

Hello, World!
1 + 2 = 3
1 + 2 + 3 = 6

Windows 应用程åºå…¥å£å‡½æ•°

  • GUI(Graphical User Interface)应用,链接器选项:/SUBSYSTEM:WINDOWS
  • CUI(Console User Interface)应用,链接器选项:/SUBSYSTEM:CONSOLE

_tWinMain 与 _tmain 函数声明

Int WINAPI _tWinMain(
    HINSTANCE hInstanceExe,
    HINSTANCE,
    PTSTR pszCmdLine,
    int nCmdShow);

int _tmain(
    int argc,
    TCHAR *argv[],
    TCHAR *envp[]);
应用程åºç±»åž‹ å…¥å£ç‚¹å‡½æ•° åµŒå…¥å¯æ‰§è¡Œæ–‡ä»¶çš„å¯åŠ¨å‡½æ•°
处ç†ANSI字符(串)的GUIåº”ç”¨ç¨‹åº _tWinMain(WinMain) WinMainCRTSartup
处ç†Unicode字符(串)的GUIåº”ç”¨ç¨‹åº _tWinMain(wWinMain) wWinMainCRTSartup
处ç†ANSI字符(串)的CUI应用ç F438 ¨‹åº _tmain(Main) mainCRTSartup
处ç†Unicode字符(串)的CUIåº”ç”¨ç¨‹åº _tmain(wMain) wmainCRTSartup
动æ€é“¾æŽ¥åº“(Dynamic-Link Library) DllMain _DllMainCRTStartup

Windows 的动æ€é“¾æŽ¥åº“(Dynamic-Link Library)

部分知识点æ¥è‡ªã€ŠWindows 核心编程(第五版)》

用处

  • 扩展了应用程åºçš„特性
  • 简化了项目管ç†
  • 有助于节çœå†…å­˜
  • 促进了资æºçš„共享
  • 促进了本地化
  • 有助于解决平å°é—´çš„差异
  • å¯ä»¥ç”¨äºŽç‰¹æ®Šç›®çš„

注æ„

  • 创建 DLL,事实上是在创建å¯ä¾›ä¸€ä¸ªå¯æ‰§è¡Œæ¨¡å—调用的函数
  • å½“ä¸€ä¸ªæ¨¡å—æä¾›ä¸€ä¸ªå†…å­˜åˆ†é…函数(mallocã€newï¼‰çš„æ—¶å€™ï¼Œå®ƒå¿…é¡»åŒæ—¶æä¾›å¦ä¸€ä¸ªå†…存释放函数(freeã€delete)
  • 在使用 C å’Œ C++ 混编的时候,è¦ä½¿ç”¨ extern "C" 修饰符
  • 一个 DLL å¯ä»¥å¯¼å‡ºå‡½æ•°ã€å˜é‡ï¼ˆé¿å…导出)ã€C++ 类(导出导入需è¦åŒç¼–译器,å¦åˆ™é¿å…导出)
  • DLL 模å—:cpp 文件中的 __declspec(dllexport) 写在 include 头文件之å‰
  • 调用 DLL çš„å¯æ‰§è¡Œæ¨¡å—:cpp 文件的 __declspec(dllimport) 之å‰ä¸åº”该定义 MYLIBAPI

加载 Windows 程åºçš„æœç´¢é¡ºåº

  1. 包å«å¯æ‰§è¡Œæ–‡ä»¶çš„目录
  2. Windows 的系统目录,å¯ä»¥é€šè¿‡ GetSystemDirectory 得到
  3. 16 ä½çš„ç³»ç»Ÿç›®å½•ï¼Œå³ Windows 目录中的 System å­ç›®å½•
  4. Windows 目录,å¯ä»¥é€šè¿‡ GetWindowsDirectory 得到
  5. 进程的当å‰ç›®å½•
  6. PATH 环境å˜é‡ä¸­æ‰€åˆ—出的目录

DLL å…¥å£å‡½æ•°

DllMain 函数

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    switch(fdwReason)
    {
    case DLL_PROCESS_ATTACH:
        // 第一次将一个DLL映射到进程地å€ç©ºé—´æ—¶è°ƒç”¨
        // The DLL is being mapped into the process' address space.
        break;
    case DLL_THREAD_ATTACH:
        // 当进程创建一个线程的时候,用于告诉DLL执行与线程相关的åˆå§‹åŒ–(éžä¸»çº¿ç¨‹æ‰§è¡Œï¼‰
        // A thread is bing created.
        break;
    case DLL_THREAD_DETACH:
        // 系统调用 ExitThread 线程退出å‰ï¼Œå³å°†ç»ˆæ­¢çš„线程通过告诉DLL执行与线程相关的清ç†
        // A thread is exiting cleanly.
        break;
    case DLL_PROCESS_DETACH:
        // 将一个DLL从进程的地å€ç©ºé—´æ—¶è°ƒç”¨
        // The DLL is being unmapped from the process' address space.
        break;
    }
    return (TRUE); // Used only for DLL_PROCESS_ATTACH
}

载入å¸è½½åº“

LoadLibraryã€LoadLibraryExAã€LoadPackagedLibraryã€FreeLibraryã€FreeLibraryAndExitThread 函数声明

// 载入库
HMODULE WINAPI LoadLibrary(
  _In_ LPCTSTR lpFileName
);
HMODULE LoadLibraryExA(
  LPCSTR lpLibFileName,
  HANDLE hFile,
  DWORD  dwFlags
);
// è‹¥è¦åœ¨é€šç”¨ Windows å¹³å°ï¼ˆUWP)应用中加载 Win32 DLL,需è¦è°ƒç”¨ LoadPackagedLibraryï¼Œè€Œä¸æ˜¯ LoadLibrary 或 LoadLibraryEx
HMODULE LoadPackagedLibrary(
  LPCWSTR lpwLibFileName,
  DWORD   Reserved
);

// å¸è½½åº“
BOOL WINAPI FreeLibrary(
  _In_ HMODULE hModule
);
// å¸è½½åº“和退出线程
VOID WINAPI FreeLibraryAndExitThread(
  _In_ HMODULE hModule,
  _In_ DWORD   dwExitCode
);

显示地链接到导出符å·

GetProcAddress 函数声明

FARPROC GetProcAddress(
  HMODULE hInstDll,
  PCSTR pszSymbolName  // åªèƒ½æŽ¥å— ANSI 字符串,ä¸èƒ½æ˜¯ Unicode
);

DumpBin.exe 查看 DLL ä¿¡æ¯

在 VS 的开å‘人员命令æç¤ºç¬¦ 使用 DumpBin.exe 坿Ÿ¥çœ‹ DLL 库的导出段(导出的å˜é‡ã€å‡½æ•°ã€ç±»å的符å·ï¼‰ã€ç›¸å¯¹è™šæ‹Ÿåœ°å€ï¼ˆRVA,relative virtual address)。如:

DUMPBIN -exports D:\mydll.dll

LoadLibrary 与 FreeLibrary æµç¨‹å›¾

LoadLibrary 与 FreeLibrary æµç¨‹å›¾

LoadLibrary

WindowsLoadLibrary

FreeLibrary

WindowsFreeLibrary

DLL 库的编写(导出一个 DLL 模å—)

DLL 库的编写(导出一个 DLL 模å—) DLL 头文件

// MyLib.h

#ifdef MYLIBAPI

// MYLIBAPI 应该在全部 DLL æºæ–‡ä»¶çš„ include "Mylib.h" 之å‰è¢«å®šä¹‰
// 全部函数/å˜é‡æ­£åœ¨è¢«å¯¼å‡º

#else

// 这个头文件被一个exeæºä»£ç æ¨¡å—包å«ï¼Œæ„味ç€å…¨éƒ¨å‡½æ•°/å˜é‡è¢«å¯¼å…¥
#define MYLIBAPI extern "C" __declspec(dllimport)

#endif

// 这里定义任何的数æ®ç»“构和符å·

// 定义导出的å˜é‡ï¼ˆé¿å…导出å˜é‡ï¼‰
MYLIBAPI int g_nResult;

// 定义导出函数原型
MYLIBAPI int Add(int nLeft, int nRight);

DLL æºæ–‡ä»¶

// MyLibFile1.cpp

// åŒ…å«æ ‡å‡†Windowså’ŒCè¿è¡Œæ—¶å¤´æ–‡ä»¶
#include <windows.h>

// DLLæºç æ–‡ä»¶å¯¼å‡ºçš„函数和å˜é‡
#define MYLIBAPI extern "C" __declspec(dllexport)

// 包å«å¯¼å‡ºçš„æ•°æ®ç»“æž„ã€ç¬¦å·ã€å‡½æ•°ã€å˜é‡
#include "MyLib.h"

// 将此DLLæºä»£ç æ–‡ä»¶çš„ä»£ç æ”¾åœ¨æ­¤å¤„
int g_nResult;

int Add(int nLeft, int nRight)
{
    g_nResult = nLeft + nRight;
    return g_nResult;
}

DLL 库的使用(è¿è¡Œæ—¶åЍæ€é“¾æŽ¥ DLL)

DLL 库的使用(è¿è¡Œæ—¶åЍæ€é“¾æŽ¥ DLL)

// A simple program that uses LoadLibrary and 
// GetProcAddress to access myPuts from Myputs.dll. 
 
#include <windows.h> 
#include <stdio.h> 
 
typedef int (__cdecl *MYPROC)(LPWSTR); 
 
int main( void ) 
{ 
    HINSTANCE hinstLib; 
    MYPROC ProcAdd; 
    BOOL fFreeResult, fRunTimeLinkSuccess = FALSE; 
 
    // Get a handle to the DLL module.
 
    hinstLib = LoadLibrary(TEXT("MyPuts.dll")); 
 
    // If the handle is valid, try to get the function address.
 
    if (hinstLib != NULL) 
    { 
        ProcAdd = (MYPROC) GetProcAddress(hinstLib, "myPuts"); 
 
        // If the function address is valid, call the function.
 
        if (NULL != ProcAdd) 
        {
            fRunTimeLinkSuccess = TRUE;
            (ProcAdd) (L"Message sent to the DLL function\n"); 
        }
        // Free the DLL module.
 
        fFreeResult = FreeLibrary(hinstLib); 
    } 

    // If unable to call the DLL function, use an alternative.
    if (! fRunTimeLinkSuccess) 
        printf("Message printed from executable\n"); 

    return 0;
}

è¿è¡Œåº“(Runtime Library)

典型程åºè¿è¡Œæ­¥éª¤

  1. æ“作系统创建进程,把控制æƒäº¤ç»™ç¨‹åºçš„å…¥å£ï¼ˆå¾€å¾€æ˜¯è¿è¡Œåº“中的æŸä¸ªå…¥å£å‡½æ•°ï¼‰
  2. å…¥å£å‡½æ•°å¯¹è¿è¡Œåº“和程åºè¿è¡ŒçŽ¯å¢ƒè¿›è¡Œåˆå§‹åŒ–(包括堆ã€I/Oã€çº¿ç¨‹ã€å…¨å±€å˜é‡æž„造等等)。
  3. å…¥å£å‡½æ•°åˆå§‹åŒ–åŽï¼Œè°ƒç”¨ main 函数,正å¼å¼€å§‹æ‰§è¡Œç¨‹åºä¸»ä½“部分。
  4. main 函数执行完毕åŽï¼Œè¿”回到入å£å‡½æ•°è¿›è¡Œæ¸…ç†å·¥ä½œï¼ˆåŒ…括全局å˜é‡æžæž„ã€å †é”€æ¯ã€å…³é—­I/O等),然åŽè¿›è¡Œç³»ç»Ÿè°ƒç”¨ç»“æŸè¿›ç¨‹ã€‚

一个程åºçš„ I/O 指代程åºä¸Žå¤–界的交互,包括文件ã€ç®¡ç¨‹ã€ç½‘络ã€å‘½ä»¤è¡Œã€ä¿¡å·ç­‰ã€‚更广义地讲,I/O 指代æ“作系统ç†è§£ä¸º “文件†的事物。

glibc å…¥å£

_start -> __libc_start_main -> exit -> _exit

其中 main(argc, argv, __environ) 函数在 __libc_start_main 里执行。

MSVC CRT å…¥å£

int mainCRTStartup(void)

执行如下æ“作:

  1. åˆå§‹åŒ–å’Œ OS 版本有关的全局å˜é‡ã€‚
  2. åˆå§‹åŒ–堆。
  3. åˆå§‹åŒ– I/O。
  4. 获å–å‘½ä»¤è¡Œå‚æ•°å’ŒçŽ¯å¢ƒå˜é‡ã€‚
  5. åˆå§‹åŒ– C 库的一些数æ®ã€‚
  6. 调用 main 并记录返回值。
  7. 检查错误并将 main 的返回值返回。

C 语言è¿è¡Œåº“(CRT)

大致包å«å¦‚下功能:

  • å¯åŠ¨ä¸Žé€€å‡ºï¼šåŒ…æ‹¬å…¥å£å‡½æ•°åŠå…¥å£å‡½æ•°æ‰€ä¾èµ–的其他函数等。
  • 标准函数:有 C 语言标准规定的C语言标准库所拥有的函数实现。
  • I/O:I/O 功能的å°è£…和实现。
  • 堆:堆的å°è£…和实现。
  • 语言实现:语言中一些特殊功能的实现。
  • 调试:实现调试功能的代ç ã€‚

C语言标准库(ANSI C)

包å«ï¼š

  • 标准输入输出(stdio.h)
  • 文件æ“作(stdio.h)
  • 字符æ“作(ctype.h)
  • 字符串æ“作(string.h)
  • 数学函数(math.h)
  • 资æºç®¡ç†ï¼ˆstdlib.h)
  • æ ¼å¼è½¬æ¢ï¼ˆstdlib.h)
  • æ—¶é—´/日期(time.h)
  • 断言(assert.h)
  • å„ç§ç±»åž‹ä¸Šçš„常数(limits.h & float.h)
  • å˜é•¿å‚数(stdarg.h)
  • éžå±€éƒ¨è·³è½¬ï¼ˆsetjmp.h)

📚 书ç±

huihut/CS-Books:📚 Computer Science Books è®¡ç®—æœºæŠ€æœ¯ç±»ä¹¦ç± PDF

语言

  • 《C++ Primer》
  • 《Effective C++》
  • 《More Effective C++》
  • 《深度探索 C++ 对象模型》
  • 《深入ç†è§£ C++11》
  • 《STL æºç å‰–æžã€‹

算法

  • 《剑指 Offer》
  • 《编程ç çŽ‘ã€‹
  • 《程åºå‘˜é¢è¯•å®å…¸ã€‹

系统

  • 《深入ç†è§£è®¡ç®—机系统》
  • 《Windows 核心编程》
  • 《Unix 环境高级编程》

网络

  • 《Unix 网络编程》
  • 《TCP/IP 详解》

å…¶ä»–

  • 《程åºå‘˜çš„自我修养》

🔱 C/C++ å‘展方å‘

C/C++ å‘展方å‘甚广,包括ä¸é™äºŽä»¥ä¸‹æ–¹å‘, 以下列举一些大厂校招岗ä½è¦æ±‚。

åŽå°/æœåС噍

ã€åŽå°å¼€å‘】

  • ç¼–ç¨‹åŸºæœ¬åŠŸæ‰Žå®žï¼ŒæŽŒæ¡ C/C++/JAVA 等开å‘语言ã€å¸¸ç”¨ç®—法和数æ®ç»“构;
  • 熟悉 TCP/UDP 网络åè®®åŠç›¸å…³ç¼–程ã€è¿›ç¨‹é—´é€šè®¯ç¼–程;
  • 了解 Pythonã€Shellã€Perl 等脚本语言;
  • 了解 MYSQL åŠ SQL 语言ã€ç¼–程,了解 NoSQL, key-value 存储原ç†ï¼›
  • å…¨é¢ã€æ‰Žå®žçš„è½¯ä»¶çŸ¥è¯†ç»“æž„ï¼ŒæŽŒæ¡æ“作系统ã€è½¯ä»¶å·¥ç¨‹ã€è®¾è®¡æ¨¡å¼ã€æ•°æ®ç»“æž„ã€æ•°æ®åº“系统ã€ç½‘络安全等专业知识;
  • 了解分布å¼ç³»ç»Ÿè®¾è®¡ä¸Žå¼€å‘ã€è´Ÿè½½å‡è¡¡æŠ€æœ¯ï¼Œç³»ç»Ÿå®¹ç¾è®¾è®¡ï¼Œé«˜å¯ç”¨ç³»ç»Ÿç­‰çŸ¥è¯†ã€‚

桌é¢å®¢æˆ·ç«¯

ã€PC 客户端开å‘】

  • 计算机软件相关专业本科或以上学历,热爱编程,基础扎实,ç†è§£ç®—法和数æ®ç»“构相关知识;
  • 熟悉 windows æ“作系统的内存管ç†ã€æ–‡ä»¶ç³»ç»Ÿã€è¿›ç¨‹çº¿ç¨‹è°ƒåº¦ï¼›
  • 熟悉 MFC/windows 界é¢å®žçŽ°æœºåˆ¶ï¼Œç†Ÿç»ƒä½¿ç”¨ VC,精通 C/C++,熟练使用 STLï¼Œä»¥åŠ Windows 下网络编程ç»éªŒï¼›
  • ç†Ÿç»ƒæŽŒæ¡ Windows 客户端开å‘ã€è°ƒè¯•,有 Windows 应用软件开å‘ç»éªŒä¼˜å…ˆï¼›
  • 对于创新åŠè§£å†³å…·æœ‰æŒ‘战性的问题充满激情,具有良好的算法基础åŠç³»ç»Ÿåˆ†æžèƒ½åŠ›ã€‚

图形学/游æˆ/VR/AR

ã€æ¸¸æˆå®¢æˆ·ç«¯å¼€å‘】

  • 计算机科学/工程相关专业本科或以上学历,热爱编程,基础扎实,ç†è§£ç®—æ³•ã€æ•°æ®ç»“æž„ã€è½¯ä»¶è®¾è®¡ç›¸å…³çŸ¥è¯†ï¼›
  • 至少掌æ¡ä¸€ç§æ¸¸æˆå¼€å‘常用的编程语言,具 C++/C# 编程ç»éªŒä¼˜å…ˆï¼›
  • 具游æˆå¼•擎(如 Unityã€Unreal)使用ç»éªŒè€…优先;
  • äº†è§£æŸæ–¹é¢çš„æ¸¸æˆå®¢æˆ·ç«¯æŠ€æœ¯ï¼ˆå¦‚图形ã€éŸ³é¢‘ã€åŠ¨ç”»ã€ç‰©ç†ã€äººå·¥æ™ºèƒ½ã€ç½‘ç»œåŒæ­¥ï¼‰è€…优先考虑;
  • 对于创新åŠè§£å†³å…·æœ‰æŒ‘战性的问题充满激情,有较强的学习能力ã€åˆ†æžåŠè§£å†³é—®é¢˜èƒ½åŠ›ï¼Œå…·å¤‡è‰¯å¥½çš„å›¢é˜Ÿåˆä½œæ„识;
  • 具阅读英文技术文档能力;
  • 热爱游æˆã€‚

测试开å‘

ã€æµ‹è¯•å¼€å‘】

  • 计算机或相关专业本科åŠä»¥ä¸Šå­¦åŽ†ï¼›
  • 一至两年的 C/C++/Python 或其他计算机语言的编程ç»éªŒï¼›
  • å…·å¤‡æ’°å†™æµ‹è¯•è®¡åˆ’ã€æµ‹è¯•用例ã€ä»¥åŠå®žçŽ°æ€§èƒ½å’Œå®‰å…¨ç­‰æµ‹è¯•çš„èƒ½åŠ›ï¼›
  • 具备实现自动化系统的能力;
  • 具备定ä½è°ƒæŸ¥äº§å“缺陷能力ã€ä»¥åŠä»£ç çº§åˆ«è°ƒè¯•缺陷的能力;
  • 工作主动积æžï¼Œæœ‰è´£ä»»å¿ƒï¼Œå…·æœ‰è‰¯å¥½çš„团队åˆä½œç²¾ç¥žã€‚

网络安全/逆å‘

ã€å®‰å…¨æŠ€æœ¯ã€‘

  • 热爱互è”网,对æ“作系统和网络安全有狂热的追求,专业ä¸é™ï¼›
  • ç†Ÿæ‚‰æ¼æ´žæŒ–掘ã€ç½‘络安全攻防技术,了解常è§é»‘客攻击手法;
  • 掌æ¡åŸºæœ¬å¼€å‘能力,熟练使用 C/C++ 语言;
  • 对数æ®åº“ã€æ“作系统ã€ç½‘ç»œåŽŸç†æœ‰è¾ƒå¥½æŽŒæ¡ï¼›
  • 具有软件逆å‘,网络安全攻防或安全系统开å‘ç»éªŒè€…优先。

嵌入å¼/物è”网

ã€åµŒå…¥å¼åº”用开å‘】

  • æœ‰è‰¯å¥½çš„ç¼–ç¨‹åŸºç¡€ï¼Œç†Ÿç»ƒæŽŒæ¡ C/C++ 语言;
  • æŽŒæ¡æ“ä½œç³»ç»Ÿã€æ•°æ®ç»“构等软件开å‘必备知识;
  • 具备较强的沟通ç†è§£èƒ½åŠ›åŠè‰¯å¥½çš„团队åˆä½œæ„识;
  • 有 Linux/Android 系统平å°çš„å¼€å‘ç»éªŒè€…优先。

音视频/æµåª’体/SDK

ã€éŸ³è§†é¢‘ç¼–è§£ç ã€‘

  1. 硕士åŠä»¥ä¸Šå­¦åŽ†ï¼Œè®¡ç®—æœºã€ä¿¡å·å¤„ç†ã€æ•°å­¦ã€ä¿¡æ¯ç±»åŠç›¸å…³ä¸“业和方å‘ï¼›
  2. 视频编解ç åŸºç¡€æ‰Žå®žï¼Œç†Ÿå¸¸ç”¨çš„ HEVC 或 H264,有较好的数字信å·å¤„ç†åŸºç¡€ï¼›
  3. æŽŒæ¡ C/C++,代ç èƒ½åŠ›å¼º, ç†Ÿæ‚‰ä¸€ç§æ±‡ç¼–语言尤佳;
  4. 较强的英文文献阅读能力;
  5. 学习能力强,具有团队å作精神,有较强的抗压能力。

计算机视觉/机器学习

ã€è®¡ç®—机视觉研究】

  • 计算机ã€åº”ç”¨æ•°å­¦ã€æ¨¡å¼è¯†åˆ«ã€äººå·¥æ™ºèƒ½ã€è‡ªæŽ§ã€ç»Ÿè®¡å­¦ã€è¿ç­¹å­¦ã€ç”Ÿç‰©ä¿¡æ¯ã€ç‰©ç†å­¦/é‡å­è®¡ç®—ã€ç¥žç»ç§‘å­¦ã€ç¤¾ä¼šå­¦/心ç†å­¦ç­‰ä¸“业,图åƒå¤„ç†ã€æ¨¡å¼è¯†åˆ«ã€æœºå™¨å­¦ä¹ ç›¸å…³ç ”ç©¶æ–¹å‘,本科åŠä»¥ä¸Šï¼Œåšå£«ä¼˜å…ˆï¼›
  • 熟练掌æ¡è®¡ç®—机视觉和图åƒå¤„ç†ç›¸å…³çš„基本算法åŠåº”用;
  • è¾ƒå¼ºçš„ç®—æ³•å®žçŽ°èƒ½åŠ›ï¼Œç†Ÿç»ƒæŽŒæ¡ C/C++ 编程,熟悉 Shell/Python/Matlab 至少一ç§ç¼–程语言;
  • åœ¨è®¡ç®—æœºè§†è§‰ã€æ¨¡å¼è¯†åˆ«ç­‰å­¦æœ¯ä¼šè®®æˆ–者期刊上å‘表论文ã€ç›¸å…³å›½é™…比赛获奖ã€åŠæœ‰ç›¸å…³ä¸“利者优先。

💯 å¤ä¹ åˆ·é¢˜ç½‘ç«™

📠é¢è¯•题目ç»éªŒ

📆 æ‹›è˜æ—¶é—´å²—ä½

👠内推

  • Github . CyC2018/Job-Recommend:🔎 互è”网内推信æ¯ï¼ˆç¤¾æ‹›ã€æ ¡æ‹›ã€å®žä¹ ï¼‰
  • Github . amusi/AI-Job-Recommend:国内公å¸äººå·¥æ™ºèƒ½æ–¹å‘ï¼ˆå«æœºå™¨å­¦ä¹ ã€æ·±åº¦å­¦ä¹ ã€è®¡ç®—机视觉和自然语言处ç†ï¼‰å²—ä½çš„æ‹›è˜ä¿¡æ¯ï¼ˆå«å…¨èŒã€å®žä¹ å’Œæ ¡æ‹›ï¼‰

👬 贡献者

📜 License

本仓库éµå¾ª CC BY-NC-SA 4.0(署å - éžå•†ä¸šæ€§ä½¿ç”¨ - ç›¸åŒæ–¹å¼å…±äº«ï¼‰ å议,转载请注明出处,ä¸å¾—用于商业目的。

CC BY-NC-SA 4.0

About

📚 C/C++ 技术é¢è¯•基础知识总结,包括语言ã€ç¨‹åºåº“ã€æ•°æ®ç»“æž„ã€ç®—法ã€ç³»ç»Ÿã€ç½‘络ã€é“¾æŽ¥è£…载库等知识åŠé¢è¯•ç»éªŒã€æ‹›è˜ã€å†…推等信æ¯ã€‚This repository is a summary of the basic knowledge of recruiting job seekers and beginners in the direction of C/C++ technology, including language, program library, data structure, algorithm, system, network, link loading library, interview experience, recruitment, recommendation, e

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C++ 90.3%
  • C 8.5%
  • CMake 1.2%
0