15、动态计算数组的大小:
int c[]={1,2,3,4};
for(int i=0;i<sizeof c/sizeof *c;i++)
c[i]++;
16、type-safe linkage:Because all functions must be declared before they are
used in C++, the opportunity for this problem to pop up is greatly diminished.
The C++ compiler refuses to declare a function automatically for you, so it’s
likely that you will include the appropriate header file. However, if for some
reason you still manage to misdeclare a function, either by declaring by hand
or including the wrong header file (perhaps one that is out of date), the name
decoration provides a safety net that is often referred to as type-safe linkage.
17、C++中函数声明可以没有标识符,如
Void f(int x,int=0,float=1.1);
Void f(int x,int,float flt) {//...}
18、常量和const
1)把const定义放进头文件里。C++中默认为内部链接(it is visible only within the file where it is defined and cannot be seen at link time by other translation units)。定义const时,必须赋值,除非用extern声明。通常C++编译器不为const创建存储空间,而是把这个定义保存在它的符号表里;但是使用extern则强制进行了存储空间的分配(Storage must be allocated because extern says
“use external linkage,” which means that several translation units must be
able to refer to the item, which requires it to have storage),再如取一个const
的地址,也进行分配空间。
Const意味着“不能改变的一块存储空间。”但是,不能在编译期间使用它的值,因为编译器在编译期间不需要知道存储的内容。如以下代码是非法的:
const int i[]={1,2,3,4};
float f[i[3]];//Illegal
不过却可以编译通过。
C默认const是外部连接的,一个const总是需要创建一块内存空间。
因为const默认是内部链接,所以不能在一个文件中定义一个const,而在另外一个文件中把它作为extern来引用。为了使const成为外部连接以便让另外一个文件可以对它引用,必须明确地把它定义为extern,如extern const int x=1;
初始化把定义和声明分开来。
2)定义指针的技巧是要标识符的开始处读它并从里向外读,const修饰“最靠近”它的那个。*与标识符相结合,而不是与类结合,虽然写成int* a这样的定义。
3)You can assign the address of a non-const object to a const pointer because
you’re simply promising not to change something that is OK to change.
However, you can’t assign the address of a const object to a non-const pointer
because then you’re saying you might change the object via the pointer. Of
course, you can always use a cast to force such an assignment, but this is bad
programming practice because you are then breaking the constness of the
object.
4)定义为char* cp="howdy";为常量字符串,是不能修改的,如果要修改字符串,则要定义成字符数组的形式。
char* cp="howdy";
*(cp+1)='a';//illegal
4)在函数内部,用const限定参数优于在参数表里用const限定参数。
void f1(const int i) {
i++; // Illegal -- compile-time error
}
不过,可以用如下的表述会更清楚:
void f2(int ic) {
const int& i = ic;
i++; // Illegal -- compile-time error
}
5)返回一个内部类型时,应当去掉const。如果按值返回一个对象时,如果不让这个对象作为一个左值,可以用const.
6)编译器将所有的临时量自动地转成为了const.
7)为了保证一个类对象为常量,引进了const成员函数:const成员函数只能对于const对象调用。不修改数据成员的任何函数都应该把它们声明为const。const函数声明和定义都应当包括const。如
class X {
int i;
public:
X(int ii);
int f() const;
};
//...
int X::f() const { return i; }
8)一个内部类型的static const可以看做是编译期间的常量。定义时对其进行初始化。
9)What if you want to create a const member function, but you’d still like to
change some of the data in the object? This is sometimes referred to as the
difference between bitwise const and logical const (also sometimes called
memberwise const). Bitwise const means that every bit in the object is
permanent, so a bit image of the object will never change. Logical const means
that, although the entire object is conceptually constant, there may be changes
on a member-by-member basis. However, if the compiler is told that an object
is const, it will jealously guard that object to ensure bitwise constness. To
effect logical constness, there are two ways to change a data member from
within a const member function.
第一种是:强制转换常属性。
class Y {
int i;
public:
Y();
void f() const;
};
Y::Y() { i = 0; }
void Y::f() const {
//! i++; // Error -- const member function
((Y*)this)->i++; // OK: cast away const-ness
// Better: use C++ explicit cast syntax:
(const_cast<Y*>(this))->i++;
}
Int main()
{
Const Y yy;
Yy.f();
}
当然有更好的技术,那就是第二种:用mutable指定在const中将要被改变的特定数据成员。
class Z {
int i;
mutable int j;
public:
Z();
void f() const;
};
Z::Z() : i(0), j(0) {}
void Z::f() const {
//! i++; // Error -- const member function
j++; // OK: mutable
}
int main() {
const Z zz;
zz.f(); // Actually changes it!
} ///:~
10)volatile语法与const是一样的,包括定义过程中的各种规则,如成员函数的访问等。volatile means “This data may change outside the knowledge of the
compiler.”Somehow, the environment is changing the data (possibly through
multitasking, multithreading or interrupts), and volatile tells the compiler not
to make any assumptions about that data, especially during optimization.
You create volatile objects using the same syntax that you use to create
const objects. You can also create const volatile objects, which can’t be
changed by the client programmer but instead change through some outside
agency.
二、注意点
1、讯速进行分析和设计并对提出的系统执行测试是相当重要的。
2、设计对象开发准则:让特定问题成为一个类;发现所需要的类,是设计系统的主要内容;开始编程,让一部分能够运行;尽量保持简单。
3、为向OOP转换的策略:首先训练和做例子;再通过一个试验项目得到一个基本的感觉,然后尝试做一个“真实”的项目。
4、类型声明时,可以给参数名,编译器会忽略这些参数名。声明变量用extern(extern int a),表示变量是在文件以外定义的,或在文件后面部分才定义。
5、初始化string对象:
String s1="Hello";
String s2("hello,too");
String s3=S1+" "+s2;
#include "iostream"
#include "string"
#include "fstream"
using namespace std;
int main()
{
ifstream in("c:\\copy.txt");
ofstream out("c:\\too.txt");
string s;
while(getline(in,s)) //注意:getline将丢弃换行符,而不将他们存入string对象。
out<<s<<"\n";
return 1;
}
6、C++中常将特定平台的活动封装在一个类中,这是一个理想的解决方法。
7、说明符(specifier):
Short int ,int,long int
Float,double,long double
8、应当避免使用void指针。C++允许将任何类型的指针赋给void*,但是不允许将void指针赋给其它任何类型的指针。
9、Just as the address of an array arr[10] is produced by the array name
without the brackets (arr), the address of a function func()is produced by the
function name without the argument list (func). You can also use the more
explicit syntax &func().
10、不要在头文件中放置using directive指令。
11、全局作用解析:
::f();
12、嵌套友元
Making a structure nested doesn’t automatically give it access to private
members. To accomplish this, you must follow a particular form: first,
declare (without defining) the nested structure, then declare it as a friend,
and finally define the structure. The structure definition must be separate
from the friend declaration, otherwise it would be seen by the compiler as
a non-member.
struct Pointer;
friend struct Pointer;
struct Pointer {
private:
Holder* h;
int* p;
}
13、The only difference between a union and a class is the way the data is
stored (that is, the int and float are overlaid on the same piece of storage).
However, a union cannot be used as a base class during inheritance, which is
quite limiting from an object-oriented design standpoint。However, a “safe”
union can be encapsulated in a class。
14、不要将默认参数作为一个标志去决定执行函数的那一块,这是基本原则。在这种情况下,只要能够,就应该把函数分解成两个或多个重载的函数。
MyString::MyString() { buf = 0; }
MyString::MyString(char* str) {
buf = new Mem(strlen(str) + 1);
strcpy((char*)buf->pointer(), str);
}
如果换作如下则不好,因为将默认值作为判断的一个标志,在影响效率的同时,在函数很大时也不易维护。
MyString::MyString(char* str) {
if(!*str) { // Pointing at an empty string
buf = 0;
return;
}
buf = new Mem(strlen(str) + 1);
strcpy((char*)buf->pointer(), str);
}
15、如果两个加引号的字符数组邻接,并且它们之间没有标点,则编译器把这些字符数组连接成单个字符数组。
#include <iostream>
using namespace std;
int main() {
cout << "This is far too long to put on a "
"single line but it can be broken up with "
"no ill effects\nas long as there is no "
"punctuation separating adjacent character "
"arrays.\n";
} ///:~
16、声明为static有两层含义
变量的生存期和作用域
http://blog.163.com/zhoumhan_0351/blog/static/39954227200982104921868/
在所有函数体外定义的是全局量,加了static修饰符后不管在哪里都存放在全局区(静态区),在所有函数体外定义的static变量表示在该文件中有效,不能extern到别的文件用,在函数体内定义的static表示只在该函数体内有效。
1)生命周期是全局的,只初始化一次。
2)在某个作用域外不可访问。即在文件的外部不可以使用,使用权仅局限于本文件中。
//: C03:FileStatic.cpp
// File scope demonstration. Compiling and
// linking this file with FileStatic2.cpp
// will cause a linker error
// File scope means only available in this file:
static int fs;
int main() {
fs = 1;
} ///:~
//: C03:FileStatic2.cpp {O}
// Trying to reference fs
extern int fs;
void func() {
fs = 100;
} ///:~
17、内部连接意味着只对正编译的文件创建存储空间,别的文件名可以使用相同的标识符和全局变量,由static来指定为内部连接。
一般全局变量和函数为外部连接:函数和类之外定义的所有变量(除了const)和函数定义默认为外部连接。
18、预处理指令如:
#define PI 3.14
这样既得不到PI的址,也不能向PI传递一个指针和引用,且PI不能是用户定义的类型。PI的意义是从定义它的地方持续到文件结束的地方;预处理指令并不识别作用域,一般作为全局的。
19、移位
~非,^异或,<<,>>,<<=,>>=
如果左边的操作数是无符号的,右移是逻辑移位,所以最高位补零。如果左边的操作数是有符号数,右移可能是也可能不是逻辑移位,即结束不定的。
使用位运算效率很高。
来源:CSDN
作者:hopegrace
链接:https://blog.csdn.net/hopegrace/article/details/103976976