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);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值