CPP——记录(一)

我自己用过不少语言,cpp,java,python,html,ccs,javascript都接触过,系统学过java,cpp,也用过cpp,python和java编写过一些项目。但是呢,语言学过了都会忘记,但是过去写的代码不是毫无帮助,再次上手会非常容易。记录,就是记录一下最近用到的,之前学过但是忘记了的东西。

类内静态变量初始化

类内静态变量是不能在声明时候初始化的,如果是常量则可以。如下:

1
2
3
4
5
6
7
class C
{
static int a;
const static int b = 10;
//static int b = 10;error
};
int C::a = 10;

类内静态变量声明时候是没有分配内存的,只有在外部初始化以后,才会进行内存的分配。

使用类内函数建立线程

想要使用类的成员函数进行多线程,直接绑定是绑定不上的。下面的做法是错误的:

1
2
3
4
5
6
7
8
9
10
11
12
13
class C
{
void func()
{
//other code
}
void useFunc()
{
std::thread t = std::thread(C::func,this);
}
};
C obj;
std::thread t = std::thread(C::func,obj);

实际上是很容易理解的,因为成员函数就算是没有参数,实际上也是有一个参数的,就是变量本身。因此可以想想在建立thread的时候要像参数一样将变量传进去。但是用上面的方法仙人是不行的,因为我们不能像func(this)一样调用成员函数。如何将成员函数伪装成一个普通的函数?我们可以使用C++11中的bind:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class C
{
void func()
{
//other code
}
void useFunc()
{
std::thread t = std::thread( std::bind(&C::func,this));
}
};
C obj;
auto func = std::bind(&C::func,&obj);
func();// = obj.func()
std::thread t = std::thread(func);

可以看到,std::bind可以将成员函数包装成普通函数,也就可以传入到thread中了。而且,即使是在类内其他成员函数,也是一样可以这样调用的。

vector的坑

实际上,std::vector会动态分配内存,不是一个秘密,应该初学stl的都会明白。最近遇到了一个bug,内存泄露,一直找不到原因,后来发现是std::vector动态分配内存的原因。

首先,std::vector中内存是连续的,这意味着,在动态分配内存过程中,std::vector会把旧的内容拷贝到新的内存中去。这时候原先的引用,指针,就会失效。比如下面的例子:

1
2
3
4
5
6
std::vector<int> array(1);
int &d = array[0];
d = 100;
for(int i = 0;i!=10;++i)
array.push_back(i);
std::cout<<"d = " <<d << std::endl;

你觉得会输出什么?实际上输出什么是未定义的。当push_back调用时候,array会更换新的地址。这时候原来的引用就失效了。因此引用std::vector的内容要格外小心,如果有最大容量的话最好reserve一下。