c++笔记

c++笔记
2011年01月14日 星期五 7:24

parameter 参数  semicolon 分号   colon 冒号 argument 实参 comment 注释  curly brace 花括号  
有符号整型中其中一位作为符号位,1表示负数。
求模不是取余,if(a>b) {不断从a中减去一个b,直到出现一个小于b的非负数} else if {a<b}{ 不断把a加上一个b,直到出现一个小于b的非负数}
浮点数都是有符号的。字符串比较按asc码对应的值比较大小,按住alt+asc码,再松开alt得到所对应的字符。
const int *p=&i; 可以改变p指向的对象,但不能通过*p改变它所指向的值。
int* const p=&i;不能改变p指向的对象,但可以通过*p改变它所指向的值。
delete指针后把它置为0是个好习惯。
正数的补码是自身,负数的补码是:符号位不变,其他位取反后再加1. 电脑上的加减法是通过补码计算的。
type *function(type *p) {return p;}  传入一个地址,返回一个地址。
复制构造函数创建的临时变量存在在栈中,,由系统自动删除。
clock() 返回程序运行的时间 毫秒 <ctime> 
用typedef,const不要用#define
cin.fail()用来判断有没有到达文件尾(EOF), windows中用ctrl+z来模拟eof;
isalpha() 检测是不是字母,isdigits()检测是不是数字,isspace()检测是不是空白(换行 制表符,空格),ispunct()检测是不是标点符号,头文件<cctype> {isupper()  islower() tolower()  toupper()}
读取文件中的字符串:ifstream infile; infile.open("...\\*.*");getline(infile,str);  读取一行存入到str中 再次读取时读取的是下一行。
打开中文字符的文件名,在路径字符串前加上L;
(10*9*8*7)/(6*5*4*3) 可以分成(10/6)*(9/5)*(8/4)*(7/3)处理,这样可以防止中间值过大越界的情况。
引用在初始化的时候指向的是什么地址,之后永远都指向该地址,即使初始化时引用的是一个指针,而之后指针发生变化后也不会改变引用变量的地址。
以空字符结果的char数组和string是等价的。
函数模板,template <typename any> 也可以是用template<class any>  any可以换成任意标示符,用来代替各种类型,void function(any a,any b) 函数原型中用any来定义类型,系统自动按实参的类型,把any转换成相应的类型。
具体化函数模板,对特定类型的实参采用特别的处理,template <>function<特定类型>(特定类型 a,特定类型 b);
具体化函数模板的优先级比普通的函数模板优先级高。
函数的特征标是其参数列表,通过不同的特征标来进行函数重载。
/----------------------------adobe reader中 窗口-新建窗口 可以同时打开多个同一文件-------------------------------------------------/
在变量前面加上作用域解析操作符(::)表示使用变量的全局版本。例如 ::i。
static表示变量的作用域是当前所在的范围。
不能在多个文件中定义相同名字的全局变量,即在所有函数外面声明的变量。其他文件中要使用这个全局变量需要先在当前文件中声明:extern int i;在一个范围内,变量的作用域越小,优先级越高。创建一个当前文件的全局变量最好使用static。
在函数中初始化static变量后,当再次调用这个函数时,不会在对这个static变量初始化。
volatile 修饰符,有时候我们想要2个程序都使用某个值,编译器会把这个值拿出来放在缓存区,导致这2个值是一样的,但实际上,这个值在某些情况下已经发生改变了,我们需要的是对应时期的值,加上volatile就可以阻止编译器这么做。
mutable:在结构或类中,把某个成员变量加上mutable说明符,可以使该值在一个声明为const的结构或类变量中也可以发生改变。
const全局变量的链接性为内部,所以这时就相当于static const int i。当加上extern时链接性就是外部了,extern const int i=50(必须初始化),其他文件在使用时需要声明:extern const int i;
链接性为外部的全局变量不能放在头文件中,那样会导致包含这个头文件的多个文件重复定义这个全局变量导致出错。
使用new来设置指针语句必须位于函数中。
namespace中的名称不能在除main()之外的函数中使用。
static int count;和namespace{ int count; }都定义了一个链接性为内部的变量,而后一种方法更好,更符合C++标准。
类声明(private)中定义的函数都自动定义成内联函数。
类方法不修改调用对象时,应将其声明为const 例:声明 void function()const  定义 void class:function()const。
构造函数中使用了new时,析构函数必须使用delete。
类中创建符号常量,可以使用无名字的枚举(enum)类型或者使用static   例如  static const int i=10;。
srand((unsigned)time(NULL)*(unsigned)time(NULL));Sleep(1000);用srand设置按时间平方做种子,得到的随机数比较真。
CTRL+K,CTRL+C注释代码   CTRL+K,CTRL+U解除注释
删除对象数组需要用delete []p; 可以用于删除空指针,析构函数中用的是delete []  构造函数中也要统一用 new []
ChangeDisplaySettings(CurrentSetting,CDS_UPDATEREGISTRY)    //改变显示模式,分辨率 色彩 频率等
在为类重载操作符时,如果第一个操作项是非类的项,可以用友元函数来反转操作数的顺序,例如,重载了*操作符,用于class*double,当顺序是double*class时就不适用了,可以定义另一个函数 class operator*(double,class){ return class*double; }
构造函数要初始化私有常量和引用时,可以在构造函数后面加上冒号,并跟上要初始化变量和值,例如:class(int x,int y):num1(x),num2(y){ }
release生成的exe比debug生成的小得多。
SetConsoleTitle("title");//vs 2005之后项目使用的是unicode字符集,在“项目-属性”中将"unicode字符集"换成"多字节字符集"就行了
在类中直接存储对象的值是用内存换速度,用方法返回需要的值是用速度换内存。
转换类型函数不能指定返回类型(但是有返回值),不能有参数(参数就是类本身)例如:class operator double() { }
重载<<在定义函数时输出要显示的具体内容,并返回ostream对象的引用
类的声明中不能初始化静态成员变量,因为声明只是描述如何分配内存,但并不分配内存,可以在类外面初始化,除非静态成员是const整型或者枚举。
如果类中包含的静态数据成员在新对象创建时发生变化,则应该显式的提供一个复制构造函数 例如:class::class(const class & a) { }。
深度复制,如果类中定义了一个new初始化的指针成员,应当定义一个复制构造函数,以复制指向的数据。
DestroyWindow(HWND) 销毁窗体,进程还在。
PostQuitMessage(0) 结束自身进程。ExitProcess(1) 强制结束进程,暴力不安全,不能合理的释放资源。
创建const(包括枚举)和引用数据时进行初始化,在定后构造函数后面加上: 和用逗号分开的初始化列表.他们的初始化顺序与他们在类中的声明顺序一致。
当子类中也要重新定义某个函数时,应把基类中的这个函数声明为虚函数。基类中已经声明为 虚函数,则子类中相应函数自动成为虚函数 virtual 可添加也可不添加。为基类声明一个虚析构函数时惯例。定义函数的时候不要用virtual。
cout.setf(std::ios_base::fixed);cout.precision(2); 保持显示小数点后2位。
子类可以调用基类的公有函数  在子类的函数中用  基类名::函数名();
因为派生类与基类是不同的类型,所以不能保存在同一个数组中,但是可以用指向基类的指针数组来保存对象。这就是多态性。用这些指针来调用函数会按它所指向的对象类型来决定调用哪个虚函数。p[0]->function(); (*p[0]).function(); 但是这些指针只能调用基类已有的虚函数。如果不是虚函数,则只会调用基类的函数。
无法理解的错误经常不是由出错的位置引起,而是由别的地方引起的
普通的基类数组来保存基类和派生类对象,相同的方法都是调用基类的。
派生类对象通过自身调用函数时是调用派生类的函数。
基类的指针数组 指向派生类时,当调用非虚函数时,调用的是基类的函数,调用虚函数时,调用的是派生类的函数。
构造函数不能是虚函数,创建派生类时先调用基类的构造函数,再调用派生类的构造函数。
基类的析构函数通常用虚函数,这样由基类的指针指向派生类时,先执行派生类的析构函数,再执行基类的析构函数。
重新定义继承的方法不是重载。
如果基类的声明被重载了,则在派生类中重新定义所有的基类版本(比如 派生类只定义了一个版本,则其他版本的函数将被隐藏,无法使用)。
protected的作用是让派生类可以直接使用基类的保护成员。
包含纯虚函数的类不能用来定义对象,它是一个抽象类。纯虚函数格式: type function(argu)=0;
抽象基类(abstract base class,ABC)类型的指针数组可以同时管理多个具体类对象。
派生类中使用了动态内存分配(new),则必须为派生类显示定义析构函数,复制构造函数,复值操作符。

程序无法找到入口 C:\WINDOWS\system32下的dwmapi.dll改成任意名字

系统字体有重影 桌面右键属性 外观 效果 使用下列方式使屏幕字体边缘平滑 标准

派生类的友元函数可以通过强制转换,将派生类的引用,指针,转换为基类的引用,指针,然后使用这个引用,指针来调用基类的友元函数。
可以使用using声明一个基类的成员,即使采用的是私有派生,也可以直接使用这些成员,就像派生类的公有方法一样,using时只声明成员名,放在派生类的公有部分,例如using std::valarray<double>::max, 这里的max是一个函数名(不需要圆括号,函数特征表,返回类型)。using只适用于继承的时候,而不适用于包含的时候。
#ifndef <标识> #define <标识> #endif  <标识>可以自由命名,但每个头文件的标识必须唯一,一般在最后面加_,点.也变成_,字母全大写
#pragma comment(lib, "Lib\\libclient.lib")   //链接静态库中的函数
string.Trim() 去掉字符串两端的空格。
Cstring.find(string)找到与string完全匹配的第一个字符串的首字符索引,中文与中文标点占2个字符。ReverseFind(string)找到最后一个与string完全匹配的字符串首字符的索引。
CString.Mid(x,y)返回从x开始的y个字符。
 fatal error C1382: PCH -----------------------------重新生成解决方案。
已经在 .obj 中定义---------------------在.h,.hpp文件中定义了变量,而有多个文件包含了这些文件就会发生这样的错误。
没有找到MFC80UD.DLL--------------------工程属性->配置属性->常规->字符集"选"使用多字节字符集"
从“CString”转换为“LPSTR”--------------------     CString str;       (LPSTR)(LPCTSTR)str;
BOOL与bool不同 BOOL是int型 一般用于三值逻辑 TRUE/FALSE/ERROR  TRUE>0 FALSE=0 ERROR=-1
file.write()写入数据时,在每行的字符串后面加上"\r\n"就可以实现换行。
explicit修饰构造函数,改构造函数只能有一个参数,当构造函数声明为explicit时,则必须显式地调用改构造函数才有效。class i(100)为显式地调用构造函数,class i=100,隐式的调用构造函数,不能用于被声明为explicit的构造函数。
如果类需要一个析构函数,那么它一般也需要一个复制构造函数和赋值运算符函数。
int 转 LPCWSTR wchar_t a[20];  swprintf(a,L"%d",clock());  MessageBox(hwnd,a,L"测试结束",MB_OK);
<iostream>和<iostream.h>的区别,<iostream>中没有包含std,现在的标准一般是使用这个,<iostream.h>是早期的版本,为了兼容C程序,包含了std。
余数的正负号取决于被除数的正负性。
浮点数转2进制,整数部分除2取余转2进制,小数部分乘2取整转2进制。
抛弃float都用double吧,float只是为了适应早期的一些c程序,在内部运算时会先转化为double,增加开销。
<<左移操作符 等于乘上2的N位次方        >>右移操作符 等于除以2的N位次方 右移时,最高位原来是什么,移动后保持不变
&&时,容易失败的放前面,||时,容易成功的放前面。
重载++操作符时,前置++的参数和返回对象都应该是引用的,后置++的参数应该是引用的,返回对象不能是引用,且为了让编译器明白这是2个不同的函数重载,需要在后置++的参数中添加一个参数,该参数只需要声明一个类型,也不需要使用它。
在类中把成员函数声明为静态的,就可以不定义对象,直接用类名 class::function()来调用。
CString 转 int  _ttoi()      int 转 CString CString.format()  CString 转 string CString.GetBuffer(CString.GetLength()),字符有问题的话用多字节.
对象的创建顺序与对象的定义顺序一致,全局对象的创建顺序由编译器自行决定,静态对象只创建一次。
赋值构造函数的步骤是,先清除原来的数据内容,释放掉原来所占的内存,再进行与复制构造函数一样的操作。要先判断是不是自己给自己复制,是的话直接返回对象。必须是按引用返回。
用基类指针指向派生类对象,或者是用引用的方式时,派生类必须是以public的方式继承的才行。
派生类可以重新调整基类中的public成员,声明时使用using class::date;
析构函数一般定义成虚函数,以保证析构时调用的是本对象的析构函数。
不能定义对象的是纯虚类,就是包含声明虚函数=0的类。
模板类型函数的参数不会进行隐式转换。
FindWindow()  找句柄  FindWindowEx()已知父或子窗口句柄找句柄。
坐标(x,y)转lparam  y放在高16位,x放在低16位,DWORD lparam=y<<16+x;

关于循环效率,多重循环中,把次数多的循环放在内层,次数少的放在外层。
类中自用的常量用enum定义 enum{x=100,y=150};  缺点是编译器隐式认为这些值是int,不能保持浮点型。
派生类中有与基类同名的函数,且在基类中这个函数不是虚函数,则对于派生类对象或指针,基类的同名函数永不可见。
关键字inline用在函数定义的时候,而不是在声明时。定义在类声明中的没有循环的成员函数自动成为内联函数,但这种风格不好,建议在定义函数的时候加上inline。
不会修改类中数据成员的函数应该在函数后面加上const  例如 void function() const { }+
添加字体  ::AddFontResource (Ord.GamePath & "...\font\xxxx.ttf");     SendMessage (HWND_BROADCAST, WM_FONTCHANGE, NULL, NULL);
判断2进制数字中1的个数 i &= i-1    时间复杂度是i中1的个数,而更快的,就是用空间换时间,定义一个数组,预先把结果存放进去,那么时间复杂度就只有1了。
对象数组中的对象构造顺序与析构顺序相反。
char a[10];   gets(a) 可以接受包含空格的字符串,而cin不行,宽字符版本是 _getws().  gets()不限制上限,所以会导致数组越界的问题。cin.get(char *a ,int i,char c='\0')
_onexit(int function);可以注册函数,让他们在main()函数结束之后运行。
__FILE__  __LINE__   返回代码所在文件名和所在行。
比较字符串 CompareString(Ex)()   CompareStringOrdinal 前者按语言区域设置来对比字符串,速度慢,但效果也许会更好,后者速度快。
ANSI和Unicode之间转换 用MultiByteToWideChar 或者 WindeCharToMultiByte
CreateProcess()之前 先要把STARTUPINFO中的数据成员设置为0,除了第一个,STARTUPINFO si={sizeof(si)}。
用_beginthreadex()来取代CreateThread(),实际上,_beginthreadex()内部也会调用CreateThread()
volatile 修饰一个变量后,cpu每次从内存中取出这个值,因此才能对值的改变做出响应,否则,值被取出来存放到缓存中,即使值已经变化了,程序也不知道。
    保持数据同步的方法:设置关键段,一次只有一段代码访问它,CRITICAL_SECTION结构来声明一个变量 cs ,然后对这个变量进行初始化,使用函数 InitializeCriticalSection(&cs),对要保护的代码段两头分别加上EnterCriticalSection(&cs); LeaveCriticalSection(&cs);任何要访问同一共享资源的代码段都需要被包含在这两个函数中。当不再使用这个变量的时候,应该删除它,DeleteCriticalSection(&cs);
    但对于读取操作,我们并不介意多个代码段访问它,而只有在有写入代码段的操作时,我们才需要对资源进行保护,这时就需要用到SRWLock的功能。
首先,声明一个变量 RTL_SRWLOCK rs;    初始化: InitializeSRWLock(&rs); 对于读取操作的代码段添加 AcquireSRWLockShared(&rs);ReleaseSRWLockShared(&rs);    而对于写操作的代码段,应该添加 AcquireSRWLockExclusive(&rs);  ReleaseSRWLockShared(&rs);
    EnumWindows() 出现无法解析的外部符号 添加 #pragma comment(lib, "User32.lib")
    console程序一闪而过 是因为运行的是 启动调试,用 开始执行(不调试)就不会消失了,在调试菜单下
    __try{}  __finally{}       先执行__try中的代码块,无论执行到什么都会执行__finally中的代码块,比如goto return ,在调用这些之前先调用__finally中的代码,即使__try中的代码块导致的程序崩溃,__finally中的代码也会被执行。比如__try { cout<<*(int*)(0x00100000)<<endl; }   __finally     { MessageBox(NULL,"ASDA","ASDA",MB_OK); }
被其他进程或人为操作结束进程不会调用__finally里的代码,只有程序自身的行为会调用__finally里的代码。现在无论是正常运行还是出错都会运行__finally中的代码,为了让其只在出错的时候运行代码,需要一个特别的判断函数,BOOL AbnormalTermination(); 当AbnormalTermination()返回TRUE的时候 就是发生了错误。
    当使用__try{} __ecxept(EXCEPTION_EXECUTE_HANDLER | EXCEPTION_EXECUTE_SEARCH | EXCEPTION_CONTINUE_EXECUTION){}处理异常时,__except中的代码表明和系统说,我知道会有这个错误,并且已经准备了一些处理方法,因此系统会继续执行__except中的代码。EXCEPTION_EXECUTE_HANDLER指定__except时,完成__except中的代码后,系统认为已经完成了异常的处理,并继续执行__except{}之后的代码。
    WINBASE.H又被包含于WINDOWS.H中,然后WINDOWS.H被WINSOCK2.H包含。
    ShellExecute 无法解析的外部符号 应添加#pragma comment(lib, "shell32.lib")
    GetExceptionCode()返回异常的标识符,只能在__except中使用,放在__except中函数里也不行。
    用基类指针指向派生类,基类的成员变量已经赋值,并不代表派生类的成员变量也有值,在调用派生类的成员函数时,不能直接对基类的成员变量进行操作,因此需要给派生类的成员变量赋值后才可以操作。
    对于用于多态的函数,声明一个默认参数,如果基类和派生类的默认参数不一致,则默认参数的值是和指针的类型决定的,这是因为默认参数是在编译的时候就决定了,是静态绑定。所以 “绝不更改继承而来的缺省参数”。
    在循环中调用一个虚函数会损失不少的性能,这个时候应该把虚函数改成普通函数,或者把循环加入到类中虚函数的定义里去。
    每一个类共享一个vtables,而不是每个对象一个。
    类在继承时可以声明为虚继承,其作用时使父类的成员函数和成员变量在派生类中只定义一次、
    声明为mutable的成员变量可以被任何成员函数修改,即使这个成员函数被标记为const。
    引用和指针的差异 :语法,是使用.还是->;初始化,引用必须被初始化指向一个对象,不能为NULL,之后不能改变所引用的对象,指针则都可以;引用不能使用new和delete操作。引用在一些构造函数中必须被使用。
    static_cast  用于在继承关系的类之间进行转换。
    const_cast  用于把const转换为非const,这通常不是个好习惯,修改程序已减少使用这个。
    reinterpret_cast  最强力的转换,任何类型的转换。
    dynamic_cast  用于程序运行时的继承树之间的动态转换。失败时返回NULL,需要编译器支持RTTI才能使用。利用这个特性,就可以用dynamic_cast来测试一个对象是否是继承自某一个类的一系列类型,如果返回非空指针,它就属于这系列类型,返回NULL则表示它是其他的类型。
    另一种检测类型的方法是:用 type_info类来定义一个对象,并把要检测的对象通过typeid运算符后赋值给它 例如 type_info info=typeid(类型),再用info.name()来查看是什么类型,比如,如果是类 会返回 class 类名;结构会返回 struct 结构名;内置类型则返回 int double 等。对于有虚函数的类,typeid返回的是它所引用或所指向的类型,而如果没有虚函数不具备多态性质的类,typeid则返回它自己定义时的类型。
    还可以在一个类中定义一个函数,这个函数只要返回一个数值,用数值来代表某个类型。如果想知道一个类的父类是什么类型,可以在类中定义一个静态指针,在构造函数中使其指向父类,就可以知道父类的类型了。
    内联和宏的区别:内联会进行类型检查,容易找错,容易调试,但有时候一个函数能提高性能,但是编译器不把这个函数设置成内联,这时就需要宏来解决了。    
    函数的开销不仅仅是因为调用函数,传递参数和返回值都极大的影响了函数的性能。
    函数参数很多的时候把这些参数集合在一个类或结构中也会提高性能。
    operator重载的时候,能用+=就坚决不用+,因为用+会创建一个临时变量。
    内联构造函数和析构函数也是一个好选择。使用初始化列表的构造函数性能更高。因为不用初始化列表的时候,也会先创建一个空值对象,然后再给他们复制,所以不如一步到位来得有效率。、
    if语句中,延后声明也能提高性能,以为那个分支并不一定会被执行到。
    类中最常用的变量放在声明的最前面,有助于提高cpu的存取速度。
    内存对齐是高性能程序很重要的地方,主要是让每个对象的大小是cache line(通常32字节)的整数倍。
    函数名所代表的地址和对函数名进行&操作的结果是一样的  func ==  &func。
    define 和 const的区别,define不能控制范围,const可以保证参数,返回值,函数体不被修改,const会进行类型检查,const可以用来修饰指针。const表示只读,让其他读程序的人了解到不能更改这个值。优化器也许也会因为const产生更好的代码。
    预编译头文件的作用:把那些include进来的文件只编译一次,因为包含很多文件的时候这个时间会很长,用了预编译就可以减少时间。
    nvi机制(non-virtual interface)把虚函数声明为私有,用非虚公有成员函数来调用私有虚函数。
    CreateWindow总是返回NULL,要注意是不是回调函数出了问题。
    明明正常的函数,一直提示 缺少函数标题,原来是其中一个参数已经被#define过了,重名导致的。
    字符指针指向一个字符串,字符串是常量,不能通过这个指针来改变值,应该用字符数组来保存这个字符串,之后再对字符数组进行操作。
    在需要的时候才加载链接库LoadLibrary(),使用后再释放FreeLibrary(),可以减小程序大小。
    抽象类和接口的区别,抽象类中可以定义函数体,而接口不行,派生类可以继承抽象类的部分方法,但必须实现接口的所有方法。派生类可以继承多个接口。
    派生类和基类中完全相同的2个虚函数才会发生覆盖,否则发生隐藏。
    指针本身有地址,所以会占用空间,而引用没有,引用的地址没有意义,引用的地址就是它所引用的变量或对象的地址,引用不占空间。
    有符号整型在位移时特别要留意符号位。
    *************关于后置自增:在判断语句里 判断的时候没有自加,但在判断后所要执行的语句之前已经完成了自加。
    构造函数不能是私有的 因为私有就无法创建对象了,析构函数可以是私有的,可以用于给其他公有成员函数来显示调用。私有的析构函数可以保证对象只有new来生成,这些对象都位于堆上,当删除的时候,可以在别的成员函数中调用delete this;还能重载delete操作符,把这个操作符设置为私有,就能防止使用delete删除对象,必须由调用定义好的公有成员函数来删除对象。
    ifstream in("aa.txt"); while(in>>str){}     打开aa.txt,while循环不断取出一个词赋值给str,直到文件的末尾。
    函数内定义的static变量是 静态局部变量,不能在函数外部被改变。
    const_cast之后地址一样,但值却不一样,原因是编译器编译的时候看到const就把程序里的const对象全部按常理替换了,如果原来的对象加上了volatile,这样编译器就不做优化,每次用这个值的时候就重新去取,这样值就可以随之变化了。
    and not not_eq or_eq xor 等只是为了那些没有|^&~等符号的键盘使用的。
    main函数中argv[0]是程序本身的路径。
    double比float运算速度快 因为float在运算的时候会先转换成double,double的精度也更大,所以用double比较好,除了double占内存比较大之外。
    double (*(*(*fp3)())[10])();    fp3 is a pointer to a function that takes no arguments and returns a pointer to an array
of 10 pointers to functions that take no arguments and return doubles.
    don’t put using directives in header files.
    用指针指向一个字符串常理,不能通过该指针修改字符串常理,用数组保存一个字符串常量,就可以修改数据。
    如果函数返回一个const临时变量,那么这个临时变量不能给非const当参数。
    在类中const记不到define的效果,每个单独的类都有这个const 对象,这时可以使用static const对象,并赋值。也可以使用enum。
    当用类定义一个const对象时,这个对象只能调用const成员函数,就是那些在函数体前加上const的函数,对于那些不修改成员变量的函数,都可以加上const,可以保证,const对象和非const对象都可以使用这个成员函数。volatile语法上与const类似。
    用mutable声明的成员变量,可以在const函数中被修改。
    const用户定义对象,函数参数,函数返回值,函数体,还能更容易找出程序中的bug。
    类中取数据和些数据的函数名可以一致,参数为空时就是取,有参数时就是写,就是函数重载。
    ##记号粘合, #define FIELD(a)  char *a##_str, int a##_size;  同时定义一系列有规则变量。易于维护。
    string&做参数可以接受字符串常理,char*,string。
    可以给一个namespace起别名,比如 namespace itisaverylongnamespace 太长了,就可以起别名 namespace s=itisaverylongnamespace;  而一个无名的名字空间,其作用域是当前所在的cpp文件,主要用于放一些函数给本文件的其他地方使用,对其他文件来说不能使用这些函数,其作用和static一致,static是原来C的方式,无名名字空间是C++的方式,推荐用无名名字空间。
    名字空间中的类的友元函数与这个类必定在同一个名字空间。
    类中的私有静态成员也可以在类外被定义,但只能被定义一次,之后就不能在外部被改变。static const则可以在声明的时候就定义。
    local class是定义在一个函数中的class,不能包含static成员。
    静态成员函数不能修改非静态成员对象,也不能调用其他非静态成员函数,是因为没有this指针。
    限定一个类只能定义一个对象,把构造函数设定为私有,建立一个static 私有的该类 的定义,在定义一个公有的static函数用来返回这个对象。
    使用C语言的函数      extern "C" 函数声明;
    const 引用可以等于常量,非const引用不行。所以当函数参数是非const引用时,不能接受const对象,也不能直接接受常量。
    一个函数 参数是int *i 函数体中i++,对外面的i完全没变化,改成int *&i再i++,就会对外面的地址发生改变。
    一个类中有一个值用来记录生成的对象的数量时,要注意各种构造函数的调用,每个构造函数都应该对记录产生影响。
    指针不能只想类中的成员函数,是因为类中的成员函数地址不固定,需要按照类的地址加上一个偏移量才能得到。
    通过typename class::*p =&class.member 来定义一个p指针指向成员对象 并通过一个具体对象来调用  object.*p=xxx;类的成员函数指针的定义:typename (class::*fp)(typename)=&具体对象::func.(在类中使用时加上this).
    生成的临时变量总是const。
    在创建一个类对象时,不论是用=还是()创建的,都是调用赋值构造函数创建出来的。当对象创建出来后再使用=时,就是调用重载的=函数了 operator= ;重载=时返回如果不是按引用返回,再使用=操作符函数时就会多使用一次复制构造函数。重载=时一定不要忘记处理  自己=自己  的情况;
    强制转换,比reinterpret_cast更猛:比如把类k转成int, int i=*((int*)((unsigned char*)(&k)));
    operator  class()const{return class(xxx);}  从某个类自动转换成class的函数 期间要调用这个函数,再调用构造函数,再调用复制构造函数,很影响效率。template <typename T>  explicit x(T k) { a=xx;} 转换构造函数,只需要调用一次。
    如果只重载了前置++形式,运行后置++时自动转成前置++,反之不行
    x& operator++()     { ++i; return *this;     }前置++      x operator++(int) { x temp=*this; ++i; return temp; }后置++
    malloc和free最大的问题是不调用构造函数和析构函数。
    memset()失败的时候返回0,使用的时候需要判断一下是否成功。
    set_new_handler(函数) 当new失败的时候调用指定的函数,这个函数可以是提示,或者是换一个方案再继续分配。头文件new
    继承的时候,构造函数,析构函数,赋值函数,operator=不会继承过来,而是由新类自动生成一个新的。
    一个函数如果对基类能产生作用,那么对于继承的类也同样起作用。
    从基类private继承过来的public方法,到新类中成为private,可以从重新设置这些方法的标签为public,不需要参数和返回值,比如public:  BASE::FUNC;  之后就可以直接使用这个方法了。
    类中包含虚函数时,隐藏着一个虚函数指针,32位电脑上占4个字节,如果有很多虚函数也还是只有一个虚函数指针。
    构造函数、析构函数中调用虚函数的话多态机制无法生效,因为这个时候虚函数表还没有构建完成等原因或者是析构函数运行时派生类的有些东西已经被摧毁了。
    基类中的析构函数也可以声明为纯虚函数,而且必须要有定义,这样唯一的用途是用在当你想把基类弄成纯虚函数又不想把其他成员函数声明为纯虚函数的时候,它的派生类会自动实现析构函数的定义。
    设计容器时,比如stack,stash,可以让它们所包含的对象都派生自一个基类,这个基类自由一个纯虚析构函数,用这个基类指针指向派生出来的对象,delete这个指针时就能自动调用派生类的析构函数,如果要存储一个已经存在的类,不能重新设计它,则可以用多重继承这个类和那个基类产生一个新类,用这个新类来包含对象。
    定义一个enum如果没有声明这个enum变量,就不占空间。
    按引用返回的函数可以用作左值。
    bitset<100> b(0); 初始化位变量,包含100个位,初始化成0,头文件<bitset>

一般main函数返回0表示成功,其他则表示失败。
头文件应该使用完整的限定名(std::cout,std::string等),而不是使用using,以为并不是每个包含这个头文件的文件都需要用到using声明。
普通字符串(strlen())和宽字符串(wcslen())的长度是一样的,只是他们所占的内存大小不同。
RGB值存储在32位整数中,一般用DWORD,前8位是红色通道值,第二个8位是绿色通道值,第三个8位是蓝色通道值,最后8位是alpha通道值,决定颜色的透明程度。
只有变量才能以传引用的方式传递。
位图是指对图像中每一个像素都进行描述的一组数据,而非windows中的bmp文件格式。
重装++操作符 函数中没有参数是前置++,有参数是后置++,虽然并不用到这个参数
vc中的_asm标识的数据就是汇编代码。dx寄存器只能存放2个字节 short, eax可以存放4个字节 int
无法解析的外部符号 "extern "C" long __stdcall SendMessageW   在头文件中加入 #pragma comment(lib, "User32.lib")
函数体前定义了const之后 这个函数就只能被const对象所调用,例如: void function() const {},另外,用这种方式加了const之后,这个函数就与另一个同名函数不同,它们不属于函数重载。
线程在运行完创建时指定的函数后,线程自动就结束了。
多层多重继承时,底层使用基类的函数容易造成2意性,这些函数通常也是从上一层继承下来的,为了避免这种情况,需要在继承最上层基类的时候加上virtual 关键字 
派生类的析构函数会自动调用基类的析构函数,所以,把基类声明为虚析构函数,删除时会自动调用派生类的析构函数,从而正确的删除对象。
静态成员变量的初始化可以在公有部分定义,即使是一个私有的静态成员变量,格式 T CLASS::NAME=XXX;
派生类也共享基类的静态成员变量。
静态成员函数不能访问非静态成员变量,切不能被声明为虚函数,它不能使用this指针。
函数指针的作用是 声明一个函数指针,用来指向不同的函数(这些函数的返回类型与参数必须与函数指针想匹配),先给函数指针用一个函数名赋值,然后通过该函数指针加上参数来调用所指向的函数,所指向的函数可以改变,因此,函数指针可以动态调用不同的函数。暂时发现函数指针似乎只是为了减少代码量。
基类声明的虚函数的函数指针,用这个函数指针指向一个虚函数,然后通过派生类来调用这个函数指针也具有多态特性。再声明一个基类指针来动态的指向派生类,就很灵活了。
strcpy来复制字符串,strcpy(ch1,ch2) 如果ch1有初值并比ch2长,那么开头的部分是ch2的字符串,剩下的位置保持原来的值。
string的长度得用::length()获得,sizeof获得的大小与编译器有关,不同编译器可能不一样。
字符数组中的字符是可以改变的,而字符指针指向的字符串是不能改变的,因为所指向的字符串是常量。
    explicit 声明的构造函数 编译器会拒绝执行隐式类型转换。比如一个构造函数 class(int i) 当原计划是2个对象间进行操作,但是写成了一个对象和一个int型的值操作,这时应该报错,但是因为隐式转换的存在,这个int被转换成类,导致不易察觉的错误。另一种解决这个问题的方法是用一个中间类型来替代构造函数的参数,比如 对于上面的int,可以用ArraySize来替代,这样从int到对象就差了2级,2级的距离就不能进行隐式转换。
    在处理用户定义类型时,尽可能地使用前缀++--,它们的效率高,因为后缀++--在重载的时候必然需要定义一个临时对象来保存返回值,然后再析构掉。
    在使用new和delete时会自动执行2个步骤,先分配(或释放)内存,用的是operator new() (或者operator delete()),这2个函数就像c中的malloc和free,然后它们再自动调用类的构造函数来初始化对象(或者调用析构函数),如果有需要,我们也可以绕过new和delete,直接调用operator new和 operator delete
    += 比 + 好,因为+=不需要创建临时对象来保存值。
临时变量是没有名字的 一些函数里临时创建用来保存值的叫局部变量而不是临时变量,这些局部变量都有名字,临时变量的效率要比局部变量(命名变量)要高。
    stdio 比 iostream快不少。
    类的地址是虚函数指针的地址,之后是成员变量的地址。
    一个成员函数中调用了另一个虚函数,则这个虚函数的表现也具有多态性。
    类得静态成员、静态成员函数,是类的一部分而不是对象的一部分。静态成员变量应该在cpp文件中被显式初始化,例如
T class::date = xxx;不要放在构造函数中定义,不要在头文件中定义。要设置它的值,需要把它声明为public,或者使用一个public静态成员函数来操纵它。
    RTTI 运行时识别。(typeid(class)==typeid(*p))可以判断指针指向是不是某一个类型。
    #include <iomapip>中 setw(i):  cout<<setw(i)<<a<<endl; 让setw后跟着的下一个输出(a)的宽度至少为i。
    vector.capacity当前预定的内存对象数量,size当前拥有的内存对象数量。
    sort的第三个比较函数的参数,排序后的结果顺序中的对象对于两两比较都为true。
    template函数在调用的时候需要指定类型func<typename>。
    tie(a,b,c)可以用来接收多个用make_tuple(x,y,x)返回的值或者tuple<x,y,z> func() 样式的函数返回的值。
    lambda expression用来做为函数类型的参数,当做一个副词 格式是:
            [标识(指定某个变量<可选>)](参数)(mutable) throw()《->可选返回值类型》{操作 return} 
            标识表示是否在函数体中修改值,&表示可以修改,=表示不能修改,除非加上可选的mutable,参数不能有默认值,必须是固定数量。throw()标识着不扔出异常。
    检测内存溢出的头文件 crtdbg.h
    FILE  *pOut(nullptr);    errno_t err=freopen_s(&pOut,"reopenfile","w+",stdout); 设置检测出来的数据到指定文件中,之后cout出来的数据也全部到指定的reopenfile文件中。
    检测内存溢出的语句:(运行在debug模式)
        _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CRTDBG_ALLOC_MEM_DF);
        _CrtSetReportMode(_CRT_WARN,_CRTDBG_MODE_FILE);
        _CrtSetReportFile(_CRT_WARN,_CRTDBG_FILE_STDOUT);
    ppl.h不能和namespace std同时出现。Concurrency::parallel_for(static_cast<size_t>(0),count,[&squares](size_t n){squares[n]=(n+1);});
    STL中函数用不了,原因可能是没有使用std。
    比起debug下 ,release下可能会对某些循环做了优化。
    vector中直接取超出范围的下标会发生错误,用at(超出范围的下标)才会抛出异常。
    cout<<showbase; 按原有的格式输出数字 比如16进制以0x开头 8进制以0开头,要输入0x开头的数字需要设置cin.unsetf(ios::hex).
    cout<<setprecision(10); 设置小数点后面的位数 头文件 <iomanip>
    cout<<fixed;     保持长度,没有数字的位置填为0
    cout<<setw(5)    设置要输出对象所占位置数。当对象超过所设置的长度时不会发生截取。它的影响范围只是针对下一次输出,所以每次输出前都要重新进行设置。
    从文件的指定位置开始读取 in.seekg(int) out.seekp(int)
    为操作符 struct { unsigned int a:4; unsigned int b:4; }; a,b各占4位,所以总共占1个字节,以为struct会自动补齐成4的倍数,所以struct占4个字节,即使我们再加入6个这样的变量,变量总和4个字节 struct不需要再补齐,也还是4字节
    有两列数字 这些数字都两两相等,但其中有一个数字丢了,怎么找到这个数字 :用变量 index^=每个数字后index就是所求的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值