c/c++常见经验总结(linux)


编译时动态库和静态库

1. 静态库.a中的各符号和各.c不能重定义.
2. 动态库.so则是可以,它会覆盖定义,使用的是最左的库定义.
3. 本文件中定义总是最优先的.
4. 静态库参加链接时必须要依懒的放左边,被依赖的放右边.
5. 静态库中的文件名却是可以与外链接的c文件同名的.
6. 类静态变量的初始化顺序与ld链接顺序有关,越靠后越先初始化;与继承无关.
总结:c/c++编译时以文件为单位无先后顺序,链接或打包(产生lib)时有顺序性。

静态库生成命令

ar rcu libxxx.a *.o

动态库生成命令

cc -shared -fPIC

 

 

构造函数相关

假设有`class A{...};`
1. map<int,A> mp; 执行mp[1]=a; // 将执行1次A构造+1次A赋值(operator=)
2. for(auto item: mp) // 元素遍历时将执行copy-constructor; 对item.second的修改对mp无效;
3. for(auto& item: mp) // 加多引用将少执行copy-constructor;且可对值修改。

4. 区域内的析构顺序和造构顺序相反
5. class A; A a=A(123); <=> A a(123);
6. 当函数返回对象时,对象的地址是上级调用的局部地址,所以copy constructor只调用1次,通过多层返回也是只调1次;

 

模板template

1. typename “内嵌依赖类型名” C++默认就是解释为一个变量的。所以,为了和变量区分,必须使用typename告诉编译器.

2. template的具体化和实例化


假设template<typename T> void func(T &a,T &b){}
具体化是针对某种类型T,有特别的定义方式
template<> void func<strc>(strc &t1,strc &t2) {}
显式实例化,不用将相应的实参传递给形参才创建实例
template void func<char>(char &,char &);

 

自增自减

 

int func(int x, int y, int z)
{
printf("x=%d,y=%d,z=%d\n", x, y, z);
return x+y+z;
}

int main(int n, char** v)
{
int a = 0;
int b = func(++a, ++a, ++a); // output: 3, 3, 3
printf("a=%d, b=%d\n", a, b); // output: a=3,b=9

return 0;
}

 

 

线程相关

1. 默认情况下,信号将由主进程接收处理,就算信号处理函数是由子线程注册的
2. 每个线程均有自己的信号屏蔽字,可以使用sigprocmask函数来屏蔽某个线程对该信号的响应处理,仅留下需要处理该信号的线程来处理指定的信号。
3. 对某个信号处理函数,以程序执行时最后一次注册的处理函数为准,即在所有的线程里,同一个信号在任何线程里对该信号的处理一定相同
4. 可以使用pthread_kill对指定的线程发送信号

其他

1. std::string.assign(ptr, len); // 常规字符串len应该是不包括\0在内的,否则在比较时有问题
2. fd = open(); // 最后个参数是权限0777, 执行后受限于umask();

/latefirstcmt/7