编写: 王宇
2017-12-14
一 新标准的诞生
从使用上分类方法
- 类作者需要的
- 库作者需要的
- 所有人需要的
- 部分人需要的
新特性划分: 见表1-3
二 保证稳定性和兼容性
保持与C99兼容
- 预定义宏
C99语言标准增加的一些预定义宏,C++11同样增加了对这些宏的支持 - __func__预定义标识符
功能是返回所在函数的名字,在C++11中,标准甚至允许其使用在类或者结构体中 - _Pragma操作符
C/C++标准中,#pragma是一条预处理的指令,用来向编译器传达语言标准以外的一些信息,例如#pragma once 表示该头文件应该只被编译一次
在C++11中,标准定义了与预处理指令#pragma功能相同的操作符_Pragma,例如 _Pragma ("once"); - 变长参数的宏定义以及__VA_ARGS__
在C99标准中,变长参数的宏定义是指在宏定义中参数列表的最后一个参数为省略号,而预定义宏__VA_ARGS__则可以在宏定义的实现部分替换省略号所代表的字符串
#define PR(...) printf(__VA_ARGS__)
- 宽窄字符串的连接
C++标准中,将窄字符串(char)转换成宽字符串(wchar_t)是未定义的行为
在C++11标准中,在将窄字符串和宽字符串进行连接时,会将窄字符串转换成宽字符串,然后再与宽字符串进行连接
long long 整型
扩展的整型
5种标准的有符号整型
signed char
short int
int
long int
long long int
宏__cpluscplus__
C与C++混用头文件的典型用法
#ifidef __cplusplus extern "C" { #endif // 一些代码 #ifdef __cplusplus } #endif
C++11标准中,将__cplusplus定义为一个整型值
#if __cplusplus < 201103L #error #endif
静态断言
断言就是将一个返回值总是需要为真的判别式放在语句中,用于排除在设计的逻辑上不应该产生的情况,以迫使程序在发生异常时,退出,从而避免程序陷入逻辑的混乱
采用NDBUG宏,开始和关闭assert
- 静态断言与static_assert
assert运行时断言
C++11标准中,引入了static_assert断言,解决编译时断言
noexcept修饰符与noexcept操作符
C++98中,动态异常声明throw(int,double), C++11中被弃用
void except_func() throw(int, double){ ... }
表示函数不会抛出异常的动态异常声明throw()也被新的noexcept异常声明所取代
- noexcept
- void except_func() noexcept; 表示不抛出异常
- void except_func() noexcept(常量表达式);表达式为true不会抛出异常;flase抛出异常
- std::terminate 中断程序
快速初始化成员变量
在C++98中,支持了在类声明中使用等号“=”加初始值的方式,来初始化类中静态成员常量。这种方式我们也称之为”就地“声明。
- C++11中允许使用等号=或者花括号{}进行就地的非静态成员变量初始化
- C++11中,保留了初始化列表
非静态成员的sizeof
struct People { public: int hand; static People * all; }; int main() { People p; cout << sizeof(p.hand) << endl; // C++98中通过, C++11中通过 cout << sizeof(People::all) << endl; // C++98中通过, C++11中通过 cout << sizeof(People::hand) << endl; // C++98中错误, C++11中通过 }
扩展的friend语法
- C++11中,声明一个类为另外一个类的友元时,不再需要使用class关键字
- c++11中, 别名同样可行
- C++11中, 可以为类模板声明友元
final/override控制
- final 派生类不可覆盖它所修饰的虚函数
- override 必须重写其基类中的同名函数,否则代码将无法通过编译
模板函数的默认模板参数
外部模板
局部和匿名类型作模板实参
三 通用为本,专用为末
继承构造函数
隐藏:类具有可派生性,派生类可以自动获得基类的成员变量和接口(虚函数和纯虚函数,这里我们指的都是public派生)。不过基类的非虚函数则无法再被派生类使用了。这条规则对于类中最为特别的构造函数也不例外,如果派生类要使用基类的构造函数,通常需要在构造函数中显式声明
- C++中,使用using声明,解决以上问题
struct Base{ void f(double i) {} }; struct Derived : Base{ using Base::f; void f(int i){} }; int main(){ Base b; b.f(4.5); // Base:4.5 Derived d; d.f(4.5); // Base:4.5 }
- C++11中,扩展到构造函数(需确认编译器是否支持)
struct A{ A(int i){} A(double d, int i){} A(float f, int i, const char* c){} }; struct B : A{ using A::A // 集成构造函数 }; int main(){ B b(356); }
委派构造函数
class Info { public: Info() : Info(1) {} // 委派构造函数 Info(int i) : Info(i, 'a') {} // 既是目标构造函数,也是委托构造函数,是一种链状委托构造 Info(char e) : Info(1, e) {} private: Info(int i, char e) : type(i), name (e) {} // 目标构造函数 int type; char name; };
右值引用:移动语义和完美转发
-
指针成员与拷贝构造
-
移动语义
#include "stdafx.h" #include <iostream> class HugeMem { public: HugeMem(int size) : sz(size) { pIntData = new int[sz]; } HugeMem(const HugeMem & h) : sz(h.sz) { pIntData = new int[sz]; for (int i = 0; i < sz; i++) pIntData[i] = h.pIntData[i]; } ~HugeMem() { delete pIntData []; } int *pIntData; int sz; }; HugeMem GetTemp() { return HugeMem(1024); } int _tmain(int argc, _TCHAR* argv[]) { HugeMem a = GetTemp(); return 0; }
以上代码拷贝构造函数会被调用两次,一次是从GetTemp函数中有HugeMem()生成的一个临时值用作返回值,另外一次则由临时值构造出main中的变量a。析构函数调用了三次。这个过程如果指针指向非常大的内存时拷贝构造 的代价相当昂贵。而令人堪忧的是:临时变量的生产和销毁以及拷贝构造的发生对于程序员来说基本上是透明的,不会影响程序的正确性,因而即使该问题导致性能不佳,也不易被程序员察觉。
而关键的问题是,临时对象在构造和释放时,一去一来似乎并没有太大意义,那么我们是否可以在临时对象构造a时不分配内存,即不使用所谓的拷贝构造函数呢?
- 左值右值
判断左值和右值的方法有两种
1.在等号左边的值就称为左值而在等号右边的称为右值
2.另外在c++中还有一种判别方法就是可以取地址,有名的就是左值,不能取地址,没有名的就是右值 -
纯右值、将亡值
纯右值就是c++98中的标准右值用于标记临时变量或不根对象有关的值。
将亡值通常是被移动的对象(移为他用) -
std::move 强制转化为右值
- 移动语义的一些其他问题 ??
- 完美转发
是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。
显式转换操作符 - explicit 禁止隐形构造,即 Class1 a = 1;
列表初始化
- 初始化列表
{}初始化集合 - 防止类型收窄
一些可以使得数据变化或精度丢失的隐式类型转换- 从浮点数隐式转化为整型数
- 从高精度的浮点数转为低精度的浮点数
- 从整型转化为浮点型,如果整型数大到浮点数无法精确地表示,则也可以视为类型收窄
- 从整型转化为较低长度的整型
POD类型 Plain Old Data
非受限联合体
用户自定义自变量
内联名字空间
模板的别名
一般化SFINEA规则
四 新手易学、老兵易用
右尖括号 >的改进
C++11 标准要求编译器智能地去判断在哪些情况下>>不是右移符号
auto类型推导 - 动态推导
- 静态类型、动态类型与类型推导
静态类型和动态类型的主要区别在于对变量进行检查的时间点。对于所谓的静态类型,类型检查主要发生在编译阶段;而对于动态类型,类型检查主要发生在运行阶段 - auto的优势
最大优势就是在拥有初始化表达式的复杂类型变量声明时简化代码
可以免除程序员在一些类型声明时的麻烦,或者避免一些在类型声明时的错误
“自适应”性能够在一定程度上支持泛型的编程 - auto的使用细则
- 首先我们可以看看auto类型指示符与指针和引用之间的关系
- auto与volatile与const之间也存在着一些相互的联系
- 同一个赋值语句中,auto可以用来声明多个变量的类型,不过这些变量的类型必须相同
- auto 4种不能推导的情况
- auto不能是形参类型
- 在结构体中,非静态成员的类型不能是auto
- char x[3]; auto y = x; 可以 auto z[3] = x;不可以
- vector v = {1}; 不可以
decltype - 静态推导
- typeid 与 decltype
C++中的运行时类型识别(RTTI)是为每个类型产生一个type_info类型的数据,程序员可以在程序中使用typeid随时查询一个变量的类型,typeid就会返回变量相应的type_info数据。而type_info的name成员函数可以返回类型的名字。而在C++11中,又增加了hash_code这个成员函数,返回该类型唯一的哈希值,以供程序员对变量的类型随时进行比较。
RTTI还包括了C++中的dynamic_cast等特性
由于RTTI会带来一些运行时的开销,所以一些编译器会让用户选择性地关闭特性
decltype总是以一个普通的表达式为参数,返回该表达式的类型 - decltype的应用
比较典型的就是decltype与typedef/using的合用
using size_t = decltype(sizeof(0));
重用匿名类型
struct { int d; }anon_s[100]; // 匿名struct数组 int main(){ decltype(anon_s) as; as[0].d = 10; }
可以适当扩大模板泛型的能力
-
decltype推导四规则:decltype(e)
- 如果e是一个没有带括号的标记符表达式或者类成员访问表达式,那么decltype(e)就是e所命名的实体的类型。此外,如果e是一个被重载的函数,则会导致编译时错误
- 否则,假设e的类型是T, 如果e是一个将亡值(xvalue),那么decltype(e)为T&&
- 否则,假设e的类型是T, 如果e是一个左值,则decltype(e)为T&
- 否则,假设e的类型是T, 则decltype(e)为T
![](C:\Users\yu.wang\Documents\My Knowledge\temp\ueditor_temp/17cd155a-baf2-462b-a274-458a1a17735b/17cd155a-baf2-462b-a274-458a1a17735b_files/c11-1.png)
-
cv限制符的继承与冗余的符号
与auto类型推导时不带“带走”cv限制符不同,decltype是能够“带走”表达式的cv限制符。cv 指 const、volatile-不做优化
追踪返回类型
- 追踪返回类型的引入
- 使用追踪返回类型的函数
基于范围的for循环
传统的for(int i = 0; i < 10; i++)和for_each均需要指定循环体其界限的范围,C++11引入了基于范围的for循环: for(int i: array)
五 提高类型安全
强类型枚举
- 枚举:分门别类与数值的名字
枚举:要定义一个类别,并穷举同一类别下的个体以供代码中使用 - 有缺陷的枚举类型
- enum的成员的名字都是全局可见的
- 枚举的成员是可以被隐式地转换为整型
- 枚举类型所占用的空间大小也是一个“不确定量”
- 强类型枚举以及C++11对原有枚举类型的扩展
针对以上缺点,C++11引入了一种新的枚举类型,即“枚举类”,又称“强类型枚举”(strong-typed enum)
例:
enum class Type {General, Light, Medium, Heavy};
优势:- 强作用域,强类型枚举成员的名字不会被输出到其父作用域空间
- 转换限制,强类型枚举成员的值不可以与整型隐式地相互转换
- 可以指定底层类型
堆内存管理:智能指针与垃圾回收
- 显式内存管理
问题:- 野指针
- 重复释放
- 内存泄漏
显式的管理内存在性能上有一定的优势,但也被广泛地认为是容易出错的。随着多线程程序的出现和广泛使用,内存管理不佳的情况还可能会变得更加严重
-
C++11 的智能指针
C++11 标准中废弃了auto_ptr- unique_ptr : 不能复制,不能转移所有权
- shared_ptr :
- weak_ptr
-
垃圾回收的分类
- 基于引用计数的垃圾回收器
- 基于跟踪处理的垃圾回收器
- 标记 —— 清除(Mark-Sweep)
首先该算法将程序中正在使用的对象视为“根对象”,从根对象开始查找它们所引用的堆空间,并在这些堆空间上做标记。当标记结束后,所有被标记的对象就是可达对象(Reachable Object)或活对象(Live Object),而没有被标记的对象就被认为是垃圾,在第二步的清扫(Sweep)阶段会被回收掉。这种方法的特点是活的对象不会被移动,但是其村子会出现大量的内存碎片的问题。 - 标记 —— 整理(Mark-Compact)
同上,标记完后,不再遍历所有对象清扫垃圾了,而是将活的对象向“左”靠齐,这就解决了内存碎片的问题。 - 标记 —— 拷贝(Mark ——Copy)
将对空间分为两个部分:From和To 刚开始系统只从From的堆空间里面分配内存,当From分配满的时候系统就开始垃圾回收:从From堆空间找出所有活的对象,拷贝到To的堆空间里。这样一来,From的堆空间里面就全剩下垃圾了。而对象被拷贝到To里之后,在To里是紧凑排列的。接下来是需要将From和To交换一下角色,接着从新的From里面开始分配。标记——拷贝算法的一个问题是堆的利用率只有一半,而且也需要移动活的对象
-
C++与垃圾回收
垃圾回收库: Boehm
C++11标准中,最小垃圾回收支持
不安全源自于CC++语言对指针的“放纵”,即允许过分灵活的使用 -
C++11与最小垃圾回收支持
首先定义安全派生指针,在C++11的规则中,最小垃圾回收支持是基于安全派生指针这个概念的
通过get_pointer_safety函数确认编译器是否支持最小垃圾回收 -
垃圾回收的兼容性
六 提高性能及操作硬件的能力
常量表达式
- 运行时常量性与编译时常量性
运行时常量: const 修饰
编译时常量: array[常量]
C语言: 宏的方式定义编译时常量
C++: constexpr
constexpr int GetConst() {return 1;} - 常量表达式函数
基本没用 - 常量表达式的其他应用
变长模板
- 变长函数和变长的模板参数
- 变长模板:模板参数包和函数参数包
- 变长模板:进阶
原子类型与原子操作
- 并行编程、多线程与C++11
- 原子操作与C++11原子类型
原子操作:就是多线程程序中“最小的且不可并行化的”的操作
原子操作都是通过“互斥”(mutual exclusive)的访问来保证的
C++11 中通过#include 头文件中来使用对应于内置类型的原子类型定义,更为普遍地,程序员可以使用atomic类模板 - 内存模型,顺序一致性与memory_order
内存模型:顺序一致性是一种内存模型之一
顺序一致性:与采用互斥,使多线程顺序同步
memory_order: 表6-3
线程局部存储
线程局部存储:拥有线程生命期及线程可见性的变量
线程会拥有自己的栈空间,但是堆空间、静态数据区则是共享的。
快速退出: quick_exit 与at_quick_exit
- terminate():C++的异常退出,只要C++程序中出现了非程序员预期的行为,都有可能导致terminate的调用
- about():相对更加低层,不会调用任何析构,默认情况下,向系统发送signal信号
- exit() : 正常退出
七 为改变思考方式而改变
指针空值 —— nullptr
- 指针空值:从0到NULL,再到nullptr
未初始化的悬挂指针通常会是一些难于调试的用户程序的错误根源
NULL是一个为0的宏
nullptr是一个所谓“指针空值类型”的常量: typedef decltype(nullptr) nullptr_t;
在C++11代码想使用NULL的时候,将NULL替换成为nullptr我们就能获得更加健壮的代码 - nullptr和nullptr_t
- 一些关于nullptr规则的讨论
- nullptr类型数据所占用的内存空间大小跟void相同, sizeof(nullptr_t) == sizeof(void)
- nullptr是一个编译时期的常量,nullptr到任何指针的转换时隐士的,而(void*)0则必须经过类型转换后才能使用
- C++11标准并没有禁止声明一个nullptr的右值引用,并打印其地址。需要记得的仅仅是,不要对nullptr做取地址操作即可
默认函数的控制
- 类与默认函数
![](C:\Users\yu.wang\Documents\My Knowledge\temp\ueditor_temp/17cd155a-baf2-462b-a274-458a1a17735b/17cd155a-baf2-462b-a274-458a1a17735b_files/class_struct.png)
在C++语言规则中,一旦程序员实现了这些函数的自定义版本,则编译器不会再为该类自动生成默认版本。这时这样的规则会被程序员忘记,最常见的是声明了带参数的构造版本,则必须声明不带参数的版本以完成无参的变量初始化 - “=default”与“=deleted”
=default (显式缺省函数): 显式地指示编译器生成函数的默认版本
=deleted (删除函数): 指示编辑器不生成函数的缺省版本
目的: 为了增强对类默认函数的控制,让程序员能够更加精细地控制默认版本的函数
lambda的一些历史
- lambda的一些历史
- C++11 中的lambda函数
格式: capture mutable ->return-type{statement}- capture: 捕捉列表,捕捉上下文中的变量以供lambda函数使用
- parameters: 参数列表
- mutable: 修饰符,可以取消其常量性
- ->return-type: 返回类型
- statement: 函数体
最简方式: []{};
捕捉列表形式: - [var]表示值传递方式捕捉变量var
- [=]表示值传递方式捕捉所有父作用域的变量(包括this)
- [&var]表示引用传递捕捉变量var
- [&]表示引用传递捕捉所有父作用域的变量(包括this)
- [this]表示值传递方式捕捉当前的this指针
- [=,&a,&b]引用传递的方式捕捉a,b 值传递方式捕捉其他所有变量
- [=,a] 以值传递方式捕捉了所有变量,捕捉a重复
- [&,&this] 以引用传递方式捕捉了所有变量,再捕捉this也是一种重复
- lambda与仿函数
仿函数是编译器实现lambda的一种方式。在现阶段,通常编译器都会把lambda函数转化为一个仿函数对象。因此C++中,lambda可以视为仿函数的一种等价形式 - lambda的基础使用
- 关于lambda的一些问题及有趣的实验
int main(){ int j = 12; auto by_val_lambda = [=]{ return j + 1;}; auto by_rel_lambda = [&]{ return j + 1;}; cout << by_val_lambda() << endl; // 13 cout << by_ref_lambda() << endl; // 13 j++; cout << by_val_lambda() << endl; // 13 cout << by_ref_lambda() << endl; // 14 }
值得注意的是,程序员也可以通过decltype的方式来获得lambda函数的类型
mutable关键字:
- lambda与STL
lambda函数可以通过参数,传递给for_each,去遍历容器 - 更多的一些关于lambda的讨论
- lamba函数被设计的目的,就是要就地书写,就地使用
- [=],[&]被滥用,有可能造成意想不到的问题
融入实际应用
对齐支持
- 数据对齐
在C++语言中,我们可以通过sizeof查询数据长度,但C++语言却没有对对齐方式有关的查询或者设定进行标准化,而语言本身又允许自定义类型、模板等诸多特性。编译器无法完全找到正确的对齐方式,这会在使用时造成困难。
C++11定义的alignof函数来查看数据的对齐方式
struct ColorVector{ double r; double g; double b; double a; }; sizof(ColorVector); // 32 alignof(ColorVector); // 8
- C++11 alignof 和 alignas
alignof的操作数
通用属性
- 语言扩展到通用属性
扩展语法中比较常见的就是“属性”,属性是对语言中的实体对象(比如函数、变量、类型等)附件一些的额外注解信息,其用来是实现一些语言及非语言层面的功能,或是实现优化代码等的一种手段。
例: extern int area(int n) attribute((const));
这里的const属性告诉编译器:本函数返回值只依赖于输入,不会改变任何函数外的数据,因此没有任何副作用。在了解该信息的情况下,编辑器可以对area函数进行优化处理 - C++11的通用属性
C++11 语言中的通用属性使用了左右双中括号的形式: [[attribute-list]] - 预定义的通用属性
- [[norreturn]]是用于表示不会返回的函数的。这里必须注意,不会返回和没有返回值的(void)函数的区别。没有返回值得void函数的调用完成后,调用者会接着执行函数后的代码;而不会返回的函数在被调用完成后,后续代码不会再被执行。例如:有终止应用程序语句的函数、有无限循环语句的函数、有异常抛出的函数等。
- [[carried_dependency]]则跟并行情况下的编译器优化有关。事实上,[[carries_dependcy]]主要是为了解决弱内存模型平台上使用memory_order_consume内存顺序枚举问题
Unicode支持
- 字符集、编码和Unicode
ASCII、Unicode为字符集,子这个集合中,每个字符拥有一个码位
UTF-8、UTF-16、UTF-32为基于Unicode字符集的,存储方法
UTF-8: 前两位为标识位,用于标识此字符的存储长度,例如如果是ASCII在,第一位标识位0,这时采用一个字节存储字符,如果为1有可能采用2-3个字节来表示这个字符,这样可以节省存储空间。UTF-16 直接用两个字节表示一个字符,因为Unicode中定义所有字符,长度范围:0——65535 ,用两个字节完全够用,但是这样方法浪费存储空间 - C++11 中的Unicode支持
C++11中内置类型:- char16_t : UTF-16
- char32_t : UTF-32
- chat : UTF-8
C++11字符串前缀 - u8 : UTF-8
- u : UTF-16
- U : UTF-32
C++11简明方式: 在字符串中用'\u'加4个十六进制数编码的Unicode码位(UTF——16)来标识一个Unicode字符
- 关于Unicode的库支持
locale机制,区域特征
codecvt
codecvt_utf8
codecvt_utf16
codecvt_utf8_utf16
相关推荐
《深入理解C++11》读书笔记
一本全面,详细介绍C++11的教程,同时也加入了自己的阅读笔记
总结笔记,关于侯捷翻译的《深入探索c++对象模型》的笔记 作者Lippman参与设计了全世界第一套C++编译程序cfront,这本书就是一位伟大的C++编译程序设计者向你阐述他如何处理各种explicit(明确出现于C++程序代码中)...
c++教程很经典大内培训笔记经典的入门教程2周就可以深入了解
本书基于2014年11月发布的Boost 1.57版,介绍了其中的所有129个库,并且结合C++11/14标准详细、深入地讲解了其中数十个库,同时实现了若干颇具实用价值的工具类和函数,可帮助读者迅速地理解、掌握Boost的用法并...
1.认识原子操作 原子操作就是在多线程程序中“最小的且不可并行化的”操作,意味着多个线程访问同一个资源时,有且仅有一个线程能对资源进行操作。通常情况下原子操作可以通过互斥的访问方式来保证,例如Linux下的...
内容概要: 使用特定领域库进行高效编程。本文介绍了两个具有高效性...可以选择按照自己的兴趣领域先阅读相关部分,再逐步深入了解其他功能。同时,读者可以尝试在实际项目中应用所学知识,加深对库的理解和熟练程度。
虽然书中包括了一些帮助读者将Java转化成C的提示,但是还是要求读者对C或者C++有一定的了解。 您可以通过本书的Web网站www.csapp.cs.cmu.edu获得完整的资料,包括实验和作业,授课笔记和代码示例。 本书英文版...
其他说明:大学生自己学习的过程中总结的笔记,其中不可避免的会有不完整的地方,也会由于每个人的理解程度不同,会有不同的侧重点。使用该文件中的代码的时候务必先亲自尝试,如有错误之处,还请海涵。
课程名称> 本课程针对C++程序设计和编程思想中...3,深入理解C++语言中类的设计 4,C++中的继承 5,C++项目实战《饮料自动贩卖机—模拟程序》 6,C++中的多态 7,C++中的运算符重载 8,C++模板 9,C++中的输入输出流
算法笔记上机训练实战指南》是《算法笔记》的配套习题集,内容按照《算法笔记...读者可以通过本书对《算法笔记》的知识点进行更深入的学习和理解。书中印有大量二维码,用以实时更新或补充书籍的内容及发布本书的勘误。
13)C++析构函数为什么要为虚函数15)数组操作中对于指针的深入理解 16)、锁的理解 17) C++11 并发与多线程 18)binder通信 19)LInux 1.12 C++ 基础必备: 1)内联函数和宏定义的区别?(*****) 2)sizeof size ...
深入了解 Modern C++ 裸数组传入模板函数,退化还是不退化 auto与函数模板之推导规则辨析 decltype,乃编译器之化身 别再徘徊于{}与()之间了,来学习初始化的正确用法 编译器优化之copy elision、RVO 提高C++程序员...
3、写代码有好处栈:栈中的生命周期是跟随线程,所以一般不需要关注堆:堆中的对象是垃圾回收的重点方法区/元空间:这一块也会发生垃圾回收,不过这块的效率比较低,一般
虽然书中包括了一些帮助读者将Java转化成C的提示,但是还是要求读者对C或者C++有一定的了解。 您可以通过本书的Web网站www.csapp.cs.cmu.edu获得完整的资料,包括实验和作业,授课笔记和代码示例。 本书英文版...
深入浅出让你理解什么是LLVM 深入浅出 WebAssembly 观书有感 & 学习笔记 Github链接: 序言 & 第一章 漫谈WebAssembly发展史 2019.09.17 首先,吐槽一下,第一章漫谈发展史,一谈就是90页,这也太漫了吧,截至今天才...
相关书籍推荐:为了更深入地理解数据结构,我们推荐了几本经典的教材和参考书籍。这些书籍将帮助你建立完整的数据结构知识体系。 适用人群: 这份学习资料适用于所有大学计算机相关专业的学生,无论你是初学者还是...
2012-06-11 21:00 29,184 inline-block深入理解.doc 2012-06-11 21:44 6,947,979 Linux内核完全注释V3.0书签版(带源码).rar 2012-06-11 21:31 11,599 MATLAB仿真程序OFDM程序.txt 2012-06-11 21:37 14,584,477 msdn...
引言:Java中数据传递的方式,除了基本数据类型是按照值传递,其它类型全部是按照引用传递,这和C++有很大区别,但是很多网上文章都解释的不清楚,甚至是错误的,在查阅资料之后,下面整理出一个比较容易理解的版本...
49. 深入理解C语言指针的奥秘 236 50. 游戏外挂的编写原理 254 51. 程序实例分析-为什么会陷入死循环 258 52. 空指针究竟指向了内存的哪个地方 260 53. 算术表达式的计算 265 54. 结构体对齐的具体含义 269 55. ...