C++ cheatsheet

记录学习代码过程中遇到的一些c++用法,方便以后查询,持续更新……

1. std::bind()

std::bind()是一种偏函数的用法。例如我们有一个函数体f,它由三个参数:

1
f(a,b,c);

但是我们有时只需要输入两个参数:

1
g(a,b) := f(a,4,b);

这里的g就是f的偏函数。我们可以利用std::bind()实现这种用法:

1
auto g = bind(f, _1, 4, _2);

虽然可以使functor实现这种用法,但是这种写法更清晰。

有两个常用的使用场景:

  1. 当我们使用标准库中transform, map, sort等算法时,需要传入一个可调用对象,但是我们只关心这个可调用对象中多个输入参数中的某几个,这时可以使用bind,将可调用对象参数中我们需要设置的部分填上具体的参数值:
1
2
// raise every value in vec to the power of 7
std::transform(vec.begin(), vec.end(), some_output, std::bind(std::pow, _1, 7));

上面的代码中pow函数可以输入两个参数,但是我们这里仅仅关心的是7次方。

  1. std::bind()的另一个普遍用法是和std::function()一起用作安全函数指针。这种用法通常用在回调机制中。有时一些函数需要花费很长时间完成某些任务,而我们不想要浪费时间等待他们。这时我们可以创建另一个线程运行这个函数,然后传递给它一个函数指针,当它完成任务后回调这个函数。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class MyClass {
private:
//just shorthand to avoid long typing
typedef std::function<void (float result)> TCallback;

//this function takes long time
void longRunningFunction(TCallback callback)
{
//do some long running task
//...
//callback to return result
callback(result);
}

//this function gets called by longRunningFunction after its done
void afterCompleteCallback(float result)
{
std::cout << result;
}

public:
int longRunningFunctionAsync()
{
//create callback - this equivalent of safe function pointer
auto callback = std::bind(&MyClass::afterCompleteCallback,
this, std::placeholders::_1);

//normally you want to start below function on seprate thread,
//but for illustration we will just do simple call
longRunningFunction(callback);
}
};

2. 对象实例化时,有没有new的区别

  • new创建类对象需要指针接收,一处初始化,多处使用
  • new创建类对象使用完需delete销毁
  • new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间
  • new对象指针用途广泛,比如作为函数返回值、函数参数等
  • 频繁调用场合并不适合new,就像new申请和释放内存一样

3. C++调用C函数

*Q: *项目中遇到了使用ROS调用一些其他公司编译好的驱动库。这就涉及到使用C++调用C函数的问题。通常会遇到一个常见问题:LNK2019:无法解析的外部符号。这是因为C和C++编译生成函数的机制不一样,对于一个函数foo(int, int),C编译器会为其生成_foo的符号,而C++为了支持重载,生成类似_foo_int_int的符号,这就造成符号不匹配。那么要如何解决?

*A: *在C++头文件中,使用extern "C"修饰符,将C函数或头文件包含进去。代码如下:

1
2
3
4
5
6
7
8
9
#ifdef __cplusplus  //在C++编译环境下
extern "C"
{
#endif
#include "cheader.h"
void cfoo(void);
#ifdef __cplusplus
}
#endif