C++杂物间
1. 概述2. incline3. explicit4. transfer of control bypasses initialization of: -- variable "sync"5. std::accumulate()6. String和char * 的问题7. 函数指针8. 使用宏进行数组拷贝9. memcpy函数10. lambda表达式11. mutex线程锁12. thread学习13. 使用宏进行类成员函数定义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 _Tpaccumulate(_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);