zoukankan      html  css  js  c++  java
  • C++ 容易忘的基本语法和特性

    原文链接http://blog.csdn.net/breakerzy/article/details/7271050

    标准 C++ 中容易忘记但比较重要和常用的基本语法和特性

    这是 C++ 或 C in C++,而不一定是传统 C 语言的语法和特性

    零 0

    字面量 0 是基本类型自动适应的,指针请直接使用 0 而不是 NULL 宏,如:

    1. double dval = 0;    // 0 是 double 类型,写 0.0 多余  
    2. double dval1 = 1;   // 1 是整数类型,类型提升  
    3. double dval2 = 1.0; // 1.0 是浮点类型  
    4.   
    5. class Widget {  
    6.     virtual void paint(Graphics* g) = 0;  
    7. };  

    stddef.h 中支持老代码的 NULL 定义:

    1. #ifdef __cplusplus  
    2. #define NULL    0               // 0 是各种指针类型  
    3. #else  
    4. #define NULL    ((void *) 0)    // C 中 0 是整数类型  
    5. #endif  

    数组

    由初始化自动确定大小
    1. int a1[] = {1, 2, 4, 8};  
    2. int a2[8] = {1, 2, 4, 8};   // 剩余元素初始化为 0,相当于 {1, 2, 4, 8, 0, 0, 0, 0};  
    3. int a1[8] = {};             // 或 {0},全 0 的数组  

    字符串字面量等价于数组 {}:

    1. char s1[] = "abc";  // 相当于 {'a', 'b', 'c', 0}  
    2. char s2[8] = "abc"// 相当于 {'a', 'b', 'c', 0, 0, 0, 0, 0}  
    3. char s3[8] = "";    // 或 {}, {0},全 0 的数组  

    {} 和 "" 仅用于数组初始化,不能赋值,如:s3[8] = "123",请用 strcpy(), memcpy()

    数组大小

    sizeof: 操作符取得对象和数组的字节大小(变量或类型)

    _countof: 取得数组的元素个数,只应用于数组而非指向数组的指针,在 VC 的 stdlib.h 中定义(C++ 用模板,C 用宏定义),等价于 sizeof(a)/sizeof(a[0])

    数组尾哨兵元素位置

    C++ 编译和运行环境保证,数组最后一个元素之后的一个元素的位置(地址)总是可以访问的,但不保证此地址单元内容可读写

    与此相对,不保证数组第一个元素之前的一个元素的位置(地址)可以访问,这鉴于对象、数组的内存边界对齐放置

    数组 a[N] 的尾哨兵地址:&a[N], a + N, a + _countof(a)

    STL 算法因此可以操作内部数组:

    1. char a1[]  = "abc123bca";  
    2. size_t c = _s::count(a1, a1 + _countof(a1), 'b');   // a1[] 中 b 的个数  
    数组和指针

    数组名/指针 + 整数 offset,是以数组 元素单元 为单位

    指针和大小类型

    请使用以下而不是其它 int 类型,保证 32/64 bit 移植性

    这些类型在 stddef.h, cstddef (namespace std), crtdefs.h 中定义

    • size_t: unsigned, sizeof 的结果 字节大小类型, 指针/地址值, 数组下标或元素个数
    • ptrdiff_t: signed, 指针/地址的差值
    • uintptr_t: unsigned, 指针/地址值, 同 size_t
    • intptr_t: signed, 指针/地址的差值, 同 ptrdiff_t

    STL 标准库中的很多大小和指针差值类型都是 size_t 和 ptrdiff_t 的别名,如分配器 std::allocator 中:

    1. typedef size_t      size_type;  
    2. typedef ptrdiff_t   difference_type;  
    printf 打印指针地址

    用 32/64bit 整数自定适应前缀 I,对应 ptrdiff_t (signed) 或 size_t (unsigned)

    用 printf 的变长宽度格式化 *

    1. _stprintf_s(buf, _countof(buf), _T("0x%0*IX\n"), sizeof(size_t) * 2, ptr);  

    32bit 输出:0x00000001
    64bit 输出:0x0000000000000001

    字符串字面量

    其类型是 const char_type[N] 数组,N 算上最后结尾 0 字符

    大小

    "hello": 类型是 const char[6], sizeof() = 6

    L"abc中文123": 类型是 const wchar_t[9], sizeof() = 18

    "": 类型是 const char[1], sizeof() = 1

    常量性

    请以 const char_type* 或数组作为字符串字面量的初始化、赋值左值

    有些编译器警告报错非 const 的 char_type* 初始化、赋值 (GCC),但有些编译时不报错 (VC)

    1. char* str = "abc123";  
    2. str[1] = 'B';       // 运行时 access violation  
    3.   
    4. void str_func(char* str);  
    5. str_func("abc123"); // 危险,是否修改 str 的值?  

    正确的习惯:

    1. const char* str = "abc123"// 指针指向字面量的存储,如 .rdata 只读区段  
    2. char str2[] = "abc123";     // 用字母量初始化另一个 char[] 对象的存储  
    3.   
    4. void str_func(const char* str);  
    5. void str_func2(__out char* str);    // 告诉使用者参数 str 将会修改值,约束性编程  
    转义字符
    1. wchar_t s1[] = L"abc\u4e2d\u6587";          // Unicode/UCS-2: 中 4e2d, 文 6587, Unicode 16 进制转义 \uhhhh  
    2. char s2[] = "\x61\x62\x63\xd6\xd0\xce\xc4"// GBK: 中 d0d6, 文 c4ce, 16 进制转义 \xhh  
    3. char s3[] = "\141\142\143\326\320\316\304"// 同上, GBK, 8 进制转义 \ooo  
    拼接

    编译阶段拼接,空白字符: 空格, TAB, 换行符

    1. char s[] = "hello"  
    2.            ", world";  
    链接方式

    字符串字面量的链接方式 (internal linkage) 默认使用内部链接方式,相当于使用 static 修饰

    以指针类型的模板参数只能使用指向外部链接对象的指针为例:

    1. template<const char* Name>  
    2. void str_func();  

    哪些可以作为 str_func 的模板参数 str_func<Hello>

    1. str_func<"hello">        // 错误, 直接写字面量, 内部链接  
    2. char Hello1[] = "hello"// 正确, 非 const 的字符数组, 外部链接  
    3. const char Hello2[] = "hello";        // 错误, const 全局字符数组, 内部链接, 相当于字面量  
    4. extern const char Hello3[] = "hello"// 正确, extern 显式修饰 const 全局字符数组, 外部链接  

    结构体初始化

    {} 用于初始化 POD 结构和数组,可以嵌套,常用这种方法初始化程序启动时的配置数据

    一旦 struct/class 中有自定义的构造函数,则不能再用 {} 初始化

    1. enum SEX {  
    2.     MALE,  
    3.     FEMALE  
    4. };  
    5.   
    6. // Person 中必须没有自定义构造函数  
    7. struct Person {  
    8.     int     no;  
    9.     char    nickname[16];  
    10.     char*   name;  
    11.     SEX     sex;  
    12. };  
    13.   
    14. // ss[] 可以是全局或局部变量  
    15. Person ss[] = {{42, "Mark", strdup("Mark Zuckerberg"), MALE},  
    16.                {43, "Page", strdup("Larry Page"), MALE},  
    17.                {44, "Jobs", strdup("Steve Jobs"), MALE}};  

    名字空间别名

    名字空间可以嵌套,如果名字空间很长可以用别名代替,我习惯用 _n1_n2_n3 的短别名:

    1. namespace _b_al = boost::algorithm;  

    请在较小作用域内进行名字空间导入、短别名代替,切忌放到 .h 中,防止影响范围扩散

    for 循环中的 continue 会执行步进语句

    以删除 vector 中特定元素为例,i++ 不能放到 for 的步进语句中:

    1. for (i = vec.begin(); i != vec.end();) {  
    2.     if (if_remove(i)) {  
    3.         i = vec.erase(i);  
    4.         continue;  
    5.     }  
    6.     i++;  
    7. }  

    bool 表达式短路求值

    expr1 && expr2: 只在 expr1 = true 时,才会对 expr2 求值

    expr1 || expr2: 只在 expr1 = false 时,才会对 expr2 求值

    这种技巧惯用在后边的语句依赖前面语句的时候,如:

    1. // 仅当 p != 0 时,才会访问 p->count  
    2. if (p && p->count > 42)  
  • 相关阅读:
    Oracle普通表->分区表转换(9亿数据量)
    RHEL6.4 + Oracle 11g DG测试环境快速搭建参考
    java 获取时间戳的三种方式
    java sm3加密算法
    java byte数组与String互转
    Java的多线程
    最大重叠点
    23. 客户默认选项(Default Customer Options)
    Android Studio 1.3RC版 build加速
    查看linux机器是32位还是64位的方法
  • 原文地址:https://www.cnblogs.com/wangkangluo1/p/2783905.html
Copyright © 2011-2022 走看看