8000 GitHub - 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, etc.
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

📚 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…

License

Notifications You must be signed in to change notification settings

huihut/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;      
57AE
      // 指针å˜é‡ï¼ŒæŒ‡å‘常对象
    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
{
publ
B41A
ic:
	inline void who()  // ä¸å†™inlineæ—¶éšå¼å†…è”
	{
		cout << "I am Derived\n";
	}
};

int main()
{
	// 此处的虚函数 who(),是通过类(Base)的具体对象(b)æ¥è°ƒç”¨çš„,编译期间就能确定了,所以它å¯ä»¥æ˜¯å†…è”的,但最终是å¦å†…è”å–决于编译器。 
	Base b;
	b.who();

	// æ­¤å¤„çš„è™šå‡½æ•°æ˜¯é€šè¿‡æŒ‡é’ˆè°ƒç”¨çš„ï¼Œå‘ˆçŽ°å¤šæ€æ€§ï¼Œéœ€è¦åœ¨è¿è¡Œæ—¶æœŸé—´æ‰èƒ½ç¡®å®šï¼Œæ‰€ä»¥ä¸èƒ½ä¸ºå†…è”。  
	Base *ptr = new Derived();
	ptr->who();

	// 因为Baseæœ‰è™šæžæž„函数(virtual ~Base() {}),所以 delete 时,会先调用派生类(Derivedï¼‰æžæž„函数,å†è°ƒç”¨åŸºç±»ï¼ˆBaseï¼‰æžæž„函数,防止内存泄æ¼ã€‚
	delete ptr;
	ptr = nullptr;

	system("pause");
	return 0;
} 

volatile

volatile int i = 10; 
  • volatile 关键字是一ç§ç±»åž‹ä¿®é¥°ç¬¦ï¼Œç”¨å®ƒå£°æ˜Žçš„类型å˜é‡è¡¨ç¤ºå¯ä»¥è¢«æŸäº›ç¼–译器未知的因素(æ“作系统ã€ç¡¬ä»¶ã€å…¶å®ƒçº¿ç¨‹ç­‰ï¼‰æ›´æ”¹ã€‚所以使用 volatile 告诉编译器ä¸åº”对这样的对象进行优化。
  • volatile 关键字声明的å˜é‡ï¼Œæ¯æ¬¡è®¿é—®æ—¶éƒ½å¿…须从内存中å–出值(没有被 volatile 修饰的å˜é‡ï¼Œå¯èƒ½ç”±äºŽç¼–译器的优化,从 CPU 寄存器中å–值)
  • const å¯ä»¥æ˜¯ volatile (如åªè¯»çš„状æ€å¯„存器)
  • 指针å¯ä»¥æ˜¯ volatile

assert()

断言,是å®ï¼Œè€Œéžå‡½æ•°ã€‚assert å®çš„原型定义在 <assert.h>(C)ã€<cassert>(C++)中,其作用是如果它的æ¡ä»¶è¿”å›žé”™è¯¯ï¼Œåˆ™ç»ˆæ­¢ç¨‹åºæ‰§è¡Œã€‚å¯ä»¥é€šè¿‡å®šä¹‰ NDEBUG æ¥å…³é—­ assert,但是需è¦åœ¨æºä»£ç çš„开头,include <assert.h> 之å‰ã€‚

assert() 使用

#define NDEBUG          // 加上这行,则 assert ä¸å¯ç”¨
#include <assert.h>

assert( p != NULL );    // assert ä¸å¯ç”¨

sizeof()

  • sizeof 对数组,得到整个数组所å ç©ºé—´å¤§å°ã€‚
  • sizeof 对指针,得到指针本身所å ç©ºé—´å¤§å°ã€‚

#pragma pack(n)

设定结构体ã€è”åˆä»¥åŠç±»æˆå‘˜å˜é‡ä»¥ n 字节方å¼å¯¹é½

#pragma pack(n) 使用

#pragma pack(push)  // ä¿å­˜å¯¹é½çжæ€
#pragma pack(4)     // 设定为 4 字节对é½

struct test
{
    char m1;
    double m4;
    int m3;
};

#pragma pack(pop)   // æ¢å¤å¯¹é½çжæ€

ä½åŸŸ

Bit mode: 2;    // mode å  2 ä½

ç±»å¯ä»¥å°†å…¶ï¼ˆéžé™æ€ï¼‰æ•°æ®æˆå‘˜å®šä¹‰ä¸ºä½åŸŸï¼ˆbit-field),在一个ä½åŸŸä¸­å«æœ‰ä¸€å®šæ•°é‡çš„二进制ä½ã€‚当一个程åºéœ€è¦å‘å…¶ä»–ç¨‹åºæˆ–ç¡¬ä»¶è®¾å¤‡ä¼ é€’äºŒè¿›åˆ¶æ•°æ®æ—¶ï¼Œé€šå¸¸ä¼šç”¨åˆ°ä½åŸŸã€‚

  • ä½åŸŸåœ¨å†…存中的布局是与机器有关的
  • ä½åŸŸçš„类型必须是整型或枚举类型,带符å·ç±»åž‹ä¸­çš„ä½åŸŸçš„行为将因具体实现而定
  • å–地å€è¿ç®—符(&)ä¸èƒ½ä½œç”¨äºŽä½åŸŸï¼Œä»»ä½•指针都无法指å‘类的ä½åŸŸ

extern "C"

  • 被 extern é™å®šçš„函数或å˜é‡æ˜¯ extern 类型的
  • 被 extern "C" 修饰的å˜é‡å’Œå‡½æ•°æ˜¯æŒ‰ç…§ C 语言方å¼ç¼–译和链接的

extern "C" 的作用是让 C++ 编译器将 extern "C" 声明的代ç å½“作 C 语言代ç å¤„ç†ï¼Œå¯ä»¥é¿å… C++ 因符å·ä¿®é¥°å¯¼è‡´ä»£ç ä¸èƒ½å’ŒC语言库中的符å·è¿›è¡Œé“¾æŽ¥çš„问题。

extern "C" 使用

#ifdef __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 };

decltype

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 10000 é‡è½½ä¸ºç§æœ‰

原因:在堆上生æˆå¯¹è±¡ï¼Œä½¿ç”¨ new å…³é”®è¯æ“作,其过程分为两阶段:第一阶段,使用 new 在堆上寻找å¯ç”¨å†…存,分é…给对象;第二阶段,调用构造函数生æˆå¯¹è±¡ã€‚å°† new æ“ä½œè®¾ç½®ä¸ºç§æœ‰ï¼Œé‚£ä¹ˆç¬¬ä¸€é˜¶æ®µå°±æ— æ³•完æˆï¼Œå°±ä¸èƒ½å¤Ÿåœ¨å †ä¸Šç”Ÿæˆå¯¹è±¡ã€‚

智能指针

C++ 标准库(STL)中

头文件:#include <memory>

C++ 98

std::auto_ptr<std::string> ps (new std::string(str))ï¼›

C++ 11

  1. shared_ptr
  2. unique_ptr
  3. weak_ptr
  4. auto_ptr(被 C++11 弃用)
  • Class shared_ptr å®žçŽ°å…±äº«å¼æ‹¥æœ‰ï¼ˆshared ownership)概念。多个智能指针指å‘相åŒå¯¹è±¡ï¼Œè¯¥å¯¹è±¡å’Œå…¶ç›¸å…³èµ„æºä¼šåœ¨ “最åŽä¸€ä¸ª reference 被销æ¯â€ æ—¶è¢«é‡Šæ”¾ã€‚ä¸ºäº†åœ¨ç»“æž„è¾ƒå¤æ‚的情景中执行上述工作,标准库æä¾› weak_ptrã€bad_weak_ptr å’Œ enable_shared_from_this 等辅助类。
  • Class unique_ptr 实现独å å¼æ‹¥æœ‰ï¼ˆexclusive ownership)或严格拥有(strict ownership)概念,ä¿è¯åŒä¸€æ—¶é—´å†…åªæœ‰ä¸€ä¸ªæ™ºèƒ½æŒ‡é’ˆå¯ä»¥æŒ‡å‘该对象。你å¯ä»¥ç§»äº¤æ‹¥æœ‰æƒã€‚它对于é¿å…内存泄æ¼ï¼ˆresource leak)——如 new åŽå¿˜è®° delete ——特别有用。
shared_ptr

多个智能指针å¯ä»¥å…±äº«åŒä¸€ä¸ªå¯¹è±¡ï¼Œå¯¹è±¡çš„æœ€æœ«ä¸€ä¸ªæ‹¥æœ‰ç€æœ‰è´£ä»»é”€æ¯å¯¹è±¡ï¼Œå¹¶æ¸…ç†ä¸Žè¯¥å¯¹è±¡ç›¸å…³çš„æ‰€æœ‰èµ„æºã€‚

  • 支æŒå®šåˆ¶åž‹åˆ é™¤å™¨ï¼ˆcustom deleter),å¯é˜²èŒƒ Cross-DLL 问题(对象在动æ€é“¾æŽ¥åº“(DLL)中被 new 创建,å´åœ¨å¦ä¸€ä¸ª DLL 内被 delete 销æ¯ï¼‰ã€è‡ªåŠ¨è§£é™¤äº’æ–¥é”
weak_ptr

weak_ptr å…è®¸ä½ å…±äº«ä½†ä¸æ‹¥æœ‰æŸå¯¹è±¡ï¼Œä¸€æ—¦æœ€æœ«ä¸€ä¸ªæ‹¥æœ‰è¯¥å¯¹è±¡çš„æ™ºèƒ½æŒ‡é’ˆå¤±åŽ»äº†æ‰€æœ‰æƒï¼Œä»»ä½• weak_ptr 都会自动æˆç©ºï¼ˆempty)。因此,在 default å’Œ copy 构造函数之外,weak_ptr åªæä¾› “接å—一个 shared_ptr†的构造函数。

  • 坿‰“破环状引用(cycles of referencesï¼Œä¸¤ä¸ªå…¶å®žå·²ç»æ²¡æœ‰è¢«ä½¿ç”¨çš„对象彼此互指,使之看似还在 “被使用†的状æ€ï¼‰çš„问题
unique_ptr

unique_ptr 是 C++11 æ‰å¼€å§‹æä¾›çš„类型,是一ç§åœ¨å¼‚常时å¯ä»¥å¸®åŠ©é¿å…èµ„æºæ³„æ¼çš„æ™ºèƒ½æŒ‡é’ˆã€‚采用独å å¼æ‹¥æœ‰ï¼Œæ„味ç€å¯ä»¥ç¡®ä¿ä¸€ä¸ªå¯¹è±¡å’Œå…¶ç›¸åº”的资æºåŒä¸€æ—¶é—´åªè¢«ä¸€ä¸ª pointer 拥有。一旦拥有ç€è¢«é”€æ¯æˆ–编程 empty,或开始拥有å¦ä¸€ä¸ªå¯¹è±¡ï¼Œå…ˆå‰æ‹¥æœ‰çš„那个对象就会被销æ¯ï¼Œå…¶ä»»ä½•相应资æºäº¦ä¼šè¢«é‡Šæ”¾ã€‚

  • unique_ptr 用于å–代 auto_ptr
auto_ptr

被 c++11 弃用,原因是缺ä¹è¯­è¨€ç‰¹æ€§å¦‚ “针对构造和赋值†的 std::move 语义,以åŠå…¶ä»–瑕疵。

auto_ptr 与 unique_ptr 比较
  • auto_ptr å¯ä»¥èµ‹å€¼æ‹·è´ï¼Œå¤åˆ¶æ‹·è´åŽæ‰€æœ‰æƒè½¬ç§»ï¼›unqiue_ptr æ— æ‹·è´èµ‹å€¼è¯­ä¹‰ï¼Œä½†å®žçŽ°äº†move 语义;
  • auto_ptr 对象ä¸èƒ½ç®¡ç†æ•°ç»„ï¼ˆæžæž„调用 delete),unique_ptr å¯ä»¥ç®¡ç†æ•°ç»„ï¼ˆæžæž„调用 delete[] );

强制类型转æ¢è¿ç®—符

MSDN . 强制转æ¢è¿ç®—符

static_cast

  • 用于éžå¤šæ€ç±»åž‹çš„转æ¢
  • 䏿‰§è¡Œè¿è¡Œæ—¶ç±»åž‹æ£€æŸ¥ï¼ˆè½¬æ¢å®‰å…¨æ€§ä¸å¦‚ dynamic_cast)
  • é€šå¸¸ç”¨äºŽè½¬æ¢æ•°å€¼æ•°æ®ç±»åž‹ï¼ˆå¦‚ float -> int)
  • å¯ä»¥åœ¨æ•´ä¸ªç±»å±‚次结构中移动指针,å­ç±»è½¬åŒ–为父类安全(å‘上转æ¢ï¼‰ï¼Œçˆ¶ç±»è½¬åŒ–为å­ç±»ä¸å®‰å…¨ï¼ˆå› ä¸ºå­ç±»å¯èƒ½æœ‰ä¸åœ¨çˆ¶ç±»çš„字段或方法)

å‘ä¸Šè½¬æ¢æ˜¯ä¸€ç§éšå¼è½¬æ¢ã€‚

dynamic_cast

  • 用于多æ€ç±»åž‹çš„转æ¢
  • 执行行è¿è¡Œæ—¶ç±»åž‹æ£€æŸ¥
  • åªé€‚用于指针或引用
  • 坹䏿˜Žç¡®çš„æŒ‡é’ˆçš„转æ¢å°†å¤±è´¥ï¼ˆè¿”回 nullptr),但ä¸å¼•å‘异常
  • å¯ä»¥åœ¨æ•´ä¸ªç±»å±‚次结构中移动指针,包括å‘上转æ¢ã€å‘下转æ¢

const_cast

  • 用于删除 constã€volatile å’Œ __unaligned 特性(如将 const int 类型转æ¢ä¸º int 类型 )

reinterpret_cast

  • 用于ä½çš„简å•釿–°è§£é‡Š
  • 滥用 reinterpret_cast è¿ç®—符å¯èƒ½å¾ˆå®¹æ˜“带æ¥é£Žé™©ã€‚ é™¤éžæ‰€éœ€è½¬æ¢æœ¬èº«æ˜¯ä½Žçº§åˆ«çš„,å¦åˆ™åº”使用其他强制转æ¢è¿ç®—符之一。
  • å…许将任何指针转æ¢ä¸ºä»»ä½•其他指针类型(如 char* 到 int* 或 One_class* 到 Unrelated_class* 之类的转æ¢ï¼Œä½†å…¶æœ¬èº«å¹¶ä¸å®‰å…¨ï¼‰
  • 也å…许将任何整数类型转æ¢ä¸ºä»»ä½•指针类型以åŠåå‘转æ¢ã€‚
  • reinterpret_cast è¿ç®—符ä¸èƒ½ä¸¢æŽ‰ constã€volatile 或 __unaligned 特性。
  • reinterpret_cast 的一个实际用途是在哈希函数中,å³ï¼Œé€šè¿‡è®©ä¸¤ä¸ªä¸åŒçš„值几乎ä¸ä»¥ç›¸åŒçš„索引结尾的方å¼å°†å€¼æ˜ å°„到索引。

bad_cast

  • 由于强制转æ¢ä¸ºå¼•用类型失败,dynamic_cast è¿ç®—ç¬¦å¼•å‘ bad_cast 异常。

bad_cast 使用

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

è¿è¡Œæ—¶ç±»åž‹ä¿¡æ¯ (RTTI)

dynamic_cast

  • 用于多æ€ç±»åž‹çš„转æ¢

typeid

  • typeid è¿ç®—符å…许在è¿è¡Œæ—¶ç¡®å®šå¯¹è±¡çš„类型
  • type_id 返回一个 type_info 对象的引用
  • 如果想通过基类的指针获得派生类的数æ®ç±»åž‹ï¼ŒåŸºç±»å¿…须带有虚函数
  • åªèƒ½èŽ·å–对象的实际类型

type_info

  • type_info ç±»æè¿°ç¼–译器在程åºä¸­ç”Ÿæˆçš„类型信æ¯ã€‚ 此类的对象å¯ä»¥æœ‰æ•ˆå­˜å‚¨æŒ‡å‘类型的å称的指针。 type_info 类还å¯å­˜å‚¨é€‚åˆæ¯”较两个类型是å¦ç›¸ç­‰æˆ–比较其排列顺åºçš„ç¼–ç å€¼ã€‚ 类型的编ç è§„åˆ™å’ŒæŽ’åˆ—é¡ºåºæ˜¯æœªæŒ‡å®šçš„,并且å¯èƒ½å› ç¨‹åºè€Œå¼‚。
  • 头文件:typeinfo

typeidã€type_info 使用

#include <iostream>
using namespace std;

class Flyable                       // 能飞的
{
public:
    virtual void takeoff() = 0;     // 起飞
    virtual void land() = 0;        // é™è½
};
class Bird : public Flyable         // 鸟
{
public:
    void foraging() {...}           // 觅食
    virtual void takeoff() {...}
    virtual void land() {...}
    virtual ~Bird(){}
};
class Plane : public Flyable        // 飞机
{
public:
    void carry() {...}              // è¿è¾“
    virtual void takeoff() {...}
    virtual void land() {...}
};

class type_info
{
public:
    const char* name() const;
    bool operator == (const type_info & rhs) const;
    bool operator != (const type_info & rhs) const;
    int before(const type_info & rhs) const;
    virtual ~type_info();
private:
    ...
};

void doSomething(Flyable *obj)                 // åšäº›äº‹æƒ…
{
    obj->takeoff();

    cout << typeid(*obj).name() << endl;        // 输出传入对象类型("class Bird" or "class Plane")

    if(typeid(*obj) == typeid(Bird))            // 判断对象类型
    {
        Bird *bird = dynamic_cast<Bird *>(obj); // 对象转化
        bird->foraging();
    }

    obj->land();
}

int main(){
	Bird *b = new Bird();
	doSomething(b);
	delete b;
	b = nullptr;
	return 0;
}

â­ï¸ Effective

Effective C++

  1. 视 C++ 为一个语言è”邦(Cã€Object-Oriented C++ã€Template C++ã€STL)
  2. å®å¯ä»¥ç¼–译器替æ¢é¢„处ç†å™¨ï¼ˆå°½é‡ä»¥ 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),或称八元树,是一ç§ç”¨äºŽæè¿°ä¸‰ç»´ç©ºé—´ï¼ˆåˆ’分空间)的树状数æ®ç»“æž„ã€‚å…«å‰æ ‘çš„æ¯ä¸ªèŠ‚ç‚¹è¡¨ç¤ºä¸€ä¸ªæ­£æ–¹ä½“çš„ä½“ç§¯å…ƒç´ ï¼Œæ¯ä¸ªèŠ‚ç‚¹æœ‰å…«ä¸ªå­èŠ‚ç‚¹ï¼Œè¿™å…«ä¸ªå­èŠ‚ç‚¹æ‰€è¡¨ç¤ºçš„ä½“ç§¯å…ƒç´ åŠ åœ¨ä¸€èµ·å°±ç­‰äºŽçˆ¶èŠ‚ç‚¹çš„ä½“ç§¯ã€‚ä¸€èˆ¬ä¸­å¿ƒç‚¹ä½œä¸ºèŠ‚ç‚¹çš„åˆ†å‰ä¸­å¿ƒã€‚

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

âš¡ï¸ ç®—æ³•

排åº

排åºç®—法 平凿—¶é—´å¤æ‚度 æœ€å·®æ—¶é—´å¤æ‚度 ç©ºé—´å¤æ‚度 æ•°æ®å¯¹è±¡ç¨³å®šæ€§
å†’æ³¡æŽ’åº 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 地å€ç±»åˆ« ç½‘ç»œå· ç½‘ç»œèŒƒå›´ ä¸»æœºå· 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 åªè¯»æ•°æ®æ®µï¼Œå­˜æ”¾åªè¯»æ•°æ®ï¼Œä¸€èˆ¬æ˜ 341A ¯ç¨‹åºé‡Œé¢çš„åªè¯»å˜é‡ï¼ˆå¦‚ 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_DI
F438
R /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åº”ç”¨ç¨‹åº _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…

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 25

0