C++知识点点点点点(4)

  • 静态链接库、动态链接库(共享库)、目标文件、可执行文件

C++源程序经过编译生成中间目标文件,经过链接,将中间目标文件缺少的启动代码和库代码链接进来。

静态链接库:静态链接是将中间目标文件调用的函数/过程链接到可执行文件中,成为文件的一部分。如果多个目标文件调用同一静态库中的相同部分,每个目标文件都要进行链接。

动态链接库(共享库):动态链接所调用的函数/过程并没有被拷贝到应用程序的可执行文件中去,而是仅仅在其中加入了所调用函数的描述信息。当程序运行时,才与动态库建立实际的链接关系。

*参考:https://blog.csdn.net/biggbang/article/details/44653705

 

  • new分配内存
typeName * pointer_name=new typeName;//new运算符根据数据类型确定分配的空间大小,返回地址

int * pn=new int;//pn为指针,*pn为值
.
.
delete pn;//释放new分配的内存

int * pi=new int[10];//使用new分配数组,在程序运行阶段需要才会创建,还可以更改数组大小,成为动态联编;编译时分配数组内存,为静态联编。
.
.
delete [] pi;//new与delete配对使用,new []与delete[]配对使用

delete只能用来释放new分配的内存,除此之外,delete空指针是被允许的。

 

  • 智能指针

C++11中使用的智能指针包括:unique_ptr;shared_ptr;weak_ptr。实际上智能指针是栈上的模板类对象,实现了类似指针的功能。因为智能指针是对象,如果要获取实际的裸指针,需要使用get()方法。

shared_ptr:必须使用new分配的内存:shared_ptr<string> pss (new string);

unique_ptr:必须使用new或new [ ]分配的内存:unique_ptr<double> pda (new double);unique_ptr<double [ ]> pda(new double(5))。

*参考:https://blog.csdn.net/k346k346/article/details/81478223

 

  • 指针常量与常量指针

指针(是)常量:int*const p,本质上是一个常量,指针说明指向数据的类型;指针本身是一个常量,指向的地址不能改变,其内容可以修改。

常量(的)指针:const int* p / int const *p(两者等价),本质上是一个指针,指向的内容为常量,不可改变,但指针的地址可以改变。

 

  • 串口发float数据
//串口只能以当个字节形式发送
float yaw;
uint8_t data[4]; 
p=(unsigned char*)&yaw;
data[0]=(unsigned char)(*(p+0));
data[1]=(unsigned char)(*(p+1));
data[2]=(unsigned char)(*(p+2));
data[3]=(unsigned char)(*(p+3));

 

  • 数组作为函数参数

不管函数形参何种形式,传递的均是数组的指针,相当于按地址传递。有以下几种形式的写法:

void fun1(int* param);
void fun1(int param[4]);
void fun1(int param[]);

 

  • 复制(拷贝)构造函数

调用时机当用一个对象初始化一个新的对象时(**重载赋值运算符是两个  已经存在/初始化过的对象  赋值时调用)

具体调用的场景:函数按值传递对象;函数返回对象;编译器生成临时对象(**重点就是初始化一个新的对象,就调用)

默认复制拷贝构造函数(浅复制):逐个复制非静态数据成员,按值进行复制。

浅复制的这两个特点就注定有两个隐患,以《C++ Primer》的例子来说:

class StringBad  //默认复制构造
{
private:
    int* arr=new int[4];//浅拷贝传递的为指针,同下
    char* str;//字符串指针,当进行复制构造时 sailor.str=sport.str,此时,复制的是指针的值,得到两个指向同一个
            字符串的指针,当析构一个对象,内存被释放一次,当另外一个对象再次析构时,内存将被释放两次,可能导致程序异常终止。
    int len;//按值默认复制构造正常。
    static int num_strings;//静态类成员无论创建了多少的对象,程序都只创建一个静态类成员的副本,所有对象共享同一个静态成员。
                所以在进行默认复制构造时,如果静态变量的值在创建新对象时需要改变,则需要使用深复制来显式的手动实现。
.
.
}

StringBad sport;

将默认复制构造函数改为深复制如下:

String::StringBad(const StringBad& st)
{
    int* arr=new int[4];
    std::strcpy(arr,st.arr);
    num_strings++;//手动修改静态值
    len=st.len;
    str=new char[len+1];//手动new
    std::strcpy(str,st.str);//实现按值复制
}

 

  • 递归与迭代

 

  • 空指针与野指针

空指针:没有存储任何内存地址,地址被赋值0。int* p=nullptr(C++引入)/NULL(传统C写法)

野指针:没有初始化的指针,指向未知地址。long* p; *p=223323

 

  • i++与++i

用于返回值:i++返回原值;++i返回加1后的值。

不用返回值:二者用法相同,执行效率略微不同。

++i相当于 i=i+1; return i; 左值
i++相当于 temp=i;i=i+1;return temp;右值

 

  • 多线程 join( )

调用join( )方法的线程对象在执行结束后才能返回,否则处于阻塞状态。

https://www.cnblogs.com/adorkable/p/12722209.html

 

  • volatile关键字

volatile 是一个类型修饰符。volatile 的作用是作为指令关键字,确保本条指令不会因编译器的优化而省略。

https://www.runoob.com/w3cnote/c-volatile-keyword.html

 

  • std::mutex

多个线程访问同一资源时,为了保证数据的一致性,最简单的方式就是使用 mutex(互斥锁)。

https://www.jianshu.com/p/8378e74733d6

 

  • 向量索引 "( )" 与 “[ ]”

Eigen库对两种运算符都做了重载,效果相同,如下:

    operator()(Index index)
    {
      eigen_assert(index >= 0 && index < size());
      return coeffRef(index);
    }


    operator[](Index index)
    {
      EIGEN_STATIC_ASSERT(Derived::IsVectorAtCompileTime,
                          THE_BRACKET_OPERATOR_IS_ONLY_FOR_VECTORS__USE_THE_PARENTHESIS_OPERATOR_INSTEAD)
      eigen_assert(index >= 0 && index < size());
      return coeffRef(index);
    }

但是std库只重载了 “[ ]",如下:

      operator[](size_type __n) _GLIBCXX_NOEXCEPT
      {
	__glibcxx_requires_subscript(__n);
	return *(this->_M_impl._M_start + __n);
      }

 

  • 判断两个浮点数是否相等

浮点数的比较需要考虑浮点数的精度问题,if(fabs(a-b)<=eps_0),eps_0为相等的精度。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值