C++杂物间
1. 概述
整理收集一些阅读源代码时看到的C++技巧。
2. incline
内联函数,对于简短、运行时间短的函数可以使用,需要满足无递归、无循环的条件。
普通函数:会使用栈,对局部变量、函数返回地址、形参、实参进行处理。
内联函数:直接将函数体插入到调用语句处。
incline void Test(int n){//定义函数为内联函数
std::cout<<n+1<<endl;
}
3. explicit
explicit显式关键字,用于只有一个参数的构造函数或者含有n个参数但是具有n-1个默认参数值的构造函数,表明该构造函数是显式的, 而非隐式的, 相对应的关键字是implicit,隐式的,默认情况下类构造函数的声明为implicit。
explicit Test(int n) //explicit(显式)构造函数
{
num = n;
}
4. transfer of control bypasses initialization of: – variable “sync”
谷歌翻译解释为
控制权的传递绕过了以下各项的初始化:-变量“ sync”(在第161行声明)
代码为,提示在初始互sync时出现问题,查找其他博客发现是因为switch语句出现了问题。参考
switch(m_dev_)
{
case MTI_SBG:
printf("MTI_SBG sync callback");
typedef message_filters::sync_policies::ApproximateTime
<sensor_msgs::Imu,sensor_msgs::Imu> MySyncPolicy;
message_filters::Synchronizer<MySyncPolicy> sync(MySyncPolicy(10),*imu_mti_sub,*imu_sbg_sub);//10这里出现问题
sync.registerCallback(boost::bind(&DNC::MTI_SBG_callback,this,_1,_2));
//must follow with spin();
while(ros::ok()&&(!m_chg_dev_))
{
ros::spinOnce();
}
break;
解决办法就是:在switch的每个分支上加上花括号{},或者把switch语句改成if/else。这里我加上了{}。就没有报错了
switch(m_dev_)
{
case MTI_SBG:
{
printf("MTI_SBG sync callback");
typedef message_filters::sync_policies::ApproximateTime
<sensor_msgs::Imu,sensor_msgs::Imu> MySyncPolicy;
message_filters::Synchronizer<MySyncPolicy> sync(MySyncPolicy(10),*imu_mti_sub,*imu_sbg_sub);//10这里出现问题
sync.registerCallback(boost::bind(&DNC::MTI_SBG_callback,this,_1,_2));
//must follow with spin();
while(ros::ok()&&(!m_chg_dev_))
{
ros::spinOnce();
}
break;
}
5. std::accumulate()
这是在数据校验代码中看到的,使用前面数据的累加和来进行校验,使用了**accumate()**模板函数,比较方便
return data[length() - 1] ==
std::accumulate(data, data + length() - sizeof(sum), sum);
这是原定义
/**
* @brief Accumulate values in a range.
*
* Accumulates the values in the range [first,last) using operator+(). The
* initial value is @a init. The values are processed in order.
*
* @param __first Start of range.
* @param __last End of range.
* @param __init Starting value to add other values to.
* @return The final sum.
*/
template<typename _InputIterator, typename _Tp>
inline _Tp
accumulate(_InputIterator __first, _InputIterator __last, _Tp __init)
{
// concept requirements
__glibcxx_function_requires(_InputIteratorConcept<_InputIterator>)
__glibcxx_requires_valid_range(__first, __last);
for (; __first != __last; ++__first)
__init = __init + *__first;
return __init;
}
6. String和char * 的问题
出现报错信息
deprecated conversion from string constant to ‘char*’
解决办法
- 将函数参数类型由char*改为const char
7. 函数指针
在LinkTrack中看到对函数指针的使用,比较有用,可以关注一下
这是在结构体中的声明
uint8_t (*const unpackData)(const uint8_t *data, size_t dataLength);
这是需要的函数定义
static uint8_t unpackData(const uint8_t *data, size_t dataLength) {
assert(nltNodeFrame1_.kFixedFrameLength == sizeof (frame_));
if(dataLength < nltNodeFrame1_.kFixedFrameLength || data[0] != nltNodeFrame1_.kFrameHeader || data[1] != nltNodeFrame1_.kFunctionMark) return 0;
size_t frameLength = FRAME_LENGTH(data);
if(dataLength < frameLength) return 0;
if(!verifyCheckSum(data,frameLength)) return 0;
static uint8_t initNeeded = 1;
if(initNeeded){
memset(nltNodeFrame1_.data.node,0,sizeof(nltNodeFrame1_.data.node));
initNeeded = 0;
}
memcpy(&frame_, data, nltNodeFrame1_.kFixedFrameLength);
nltNodeFrame1_.data.id =frame_.id;
nltNodeFrame1_.data.localTime =frame_.localTime;
nltNodeFrame1_.data.systemTime =frame_.systemTime;
nltNodeFrame1_.data.voltage = frame_.voltage / kVoltageMultiply_;
nltNodeFrame1_.data.validNodeCount = frame_.validNodeCount;
Node1_Raw rawNode;
for(size_t i=0;i<frame_.validNodeCount;++i){
if(!nltNodeFrame1_.data.node[i]){
nltNodeFrame1_.data.node[i] = malloc( sizeof(NLink_LinkTrack_Node1) );
}
memcpy(&rawNode,data + nltNodeFrame1_.kFixedFrameLength + i*sizeof(Node1_Raw),sizeof(Node1_Raw));
NLink_LinkTrack_Node1 *node = nltNodeFrame1_.data.node[i];
node->role = rawNode.role;
node->id = rawNode.id;
TRANSFORM_ARRAY_INT24(node->pos,rawNode.pos,kPosMultiply_)
}
return 1;
}
最后就是赋值
NLink_LinkTrack_NodeFrame1 nltNodeFrame1_ = {
.kFixedFrameLength = 27,
.kFrameHeader = 0x55,
.kFunctionMark = 0x03,
.unpackData = unpackData
};
实际调用时
void NLT_ProtocolNodeFrame1::updateData(const uint8_t *data)
{
nltNodeFrame1_.unpackData(data, length());
}
8. 使用宏进行数组拷贝
感觉这个代码很好使的样子,先做个标记。
#define ARRAY_ASSIGN(DEST, SRC) \
for (size_t _CNT = 0; _CNT < sizeof(SRC) / sizeof(SRC[0]); ++_CNT) { \
DEST[_CNT] = SRC[_CNT]; \
}
9. memcpy函数
这是原始定义
/* Copy N bytes of SRC to DEST. */
extern void *memcpy (void *__restrict __dest, const void *__restrict __src,
size_t __n) __THROW __nonnull ((1, 2));
这是一个使用示例
memcpy(&frame_, data, nltNodeFrame1_.kFixedFrameLength);
10. lambda表达式
这只是一个范例,先将就着看,以后遇到其他的再查?
[ capture list ] (parameters) -> return-type { method definition}
[](){
}
std::sort(sortInfos_.begin(), sortInfos_.end(), [](SortInfo a, SortInfo b) {
if (a.headerIndex < b.headerIndex)
return true;
else if (a.headerIndex == b.headerIndex) {
if (a.protocol->length() < b.protocol->length()) {
return true;
}
}
return false;
});
对于sort()有
/* @brief Sort the elements of a sequence using a predicate for comparison.
* @ingroup sorting_algorithms
* @param __first An iterator.
* @param __last Another iterator.
* @param __comp A comparison functor.
* @return Nothing.
*/
sort(_RandomAccessIterator __first, _RandomAccessIterator __last,
_Compare __comp)
对于lambda表达式指定返回类型,可以使用 -> int
[] (int x, int y) -> int { int z = x + y; return z; }
如果需要进行其他值,
可以使用
[&b] 引用b
[=a]值传递a
11. mutex线程锁
12. thread学习
使用join,等待子线程结束再继续执行
不使用join,直接向下执行,可能子线程未执行完毕
都挺好的,可以看看。
boost::thread的六种使用方法总结
C++ 菜鸟之路 (四) boost::thread 多线程全解析
13. 使用宏进行类成员函数定义
宏定义
#define MEMBER_PARAM_SET_GET(member, type, name, qualifier, setqualifier, getqualifier)\
getqualifier: inline type get##name() const {return member.get##name();}\
setqualifier: inline void set##name(type name) { member.set##name(name);}
类中定义,存在setgenerateMap(bool),getgenerateMap()两种成员函数
/**generate an accupancy grid map [scanmatcher]*/
MEMBER_PARAM_SET_GET(m_matcher, bool, generateMap, protected, public, public);
具体使用
gsp_->setgenerateMap(false);