Some Knowledge

一、析构函数

1.析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数。析构函数往往用来做“清理善后” 的工作(例如在建立对象时用new开辟了一片内存空间,应在退出前在析构函数中用delete释放)。
2.以C++语言为例:析构函数名也应与类名相同,只是在函数名前面加一个位取反符~,例如~stud( ),以区别于构造函数。它不能带任何参数,也没有返回值(包括void类型)。只能有一个析构函数,不能重载。如果用户没有编写析构函数,编译系统会自动生成一个缺省的析构函数,它也不进行任何操作。所以许多简单的类中没有用显示的析构函数。

二、#ifdef 和 #endif的作用

[https://www.cnblogs.com/shine-yr/p/5214978.html]

还是把头文件的内容都放在#ifndef和#endif中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识> 
#define <标识>
...... 
...... 
#endif

三、extern关键字

extern一般是使用在多文件之间需要共享某些代码时
[https://www.cnblogs.com/broglie/p/5524932.html]
[https://blog.csdn.net/aperture0/article/details/112753295]

四、C++中的STL中map用法详解

映射
[https://www.cnblogs.com/fnlingnzb-learner/p/5833051.html]

五、C++类的成员函数前加&

这个和函数参数加地址符的作用是一样的,用于返值返回的是引用而不是赋值。
也就是说,该函数返值会通过地址传送的方式给到函数调用者要求的返回值,这样可以节省对象赋值造成的内存浪费,通常用于返值是大型对象(而不是简单变量类型)的时候。
比如你有个class T,而这个函数的返值是return T; 加上地址符返值后,返回T变量的地址,将地址传递给接收返值的变量,而不是新建一个类T,调用类的复制函数创建一个新类。

六、C++/C++11中命名空间(namespace)的使用(内联命名空间inline)

[https://blog.csdn.net/fengbingchun/article/details/78575978]

七、数学函数 ceil(), floor(), round()

ceil(x)返回不小于x的最小整数值(然后转换为double型)。
floor(x)返回不大于x的最大整数值。
round(x)返回x的四舍五入整数值。

八、reserve和resize的区别

reserve是容器预留空间,但并不真正创建元素对象,在创建对象之前,不能引用容器内的元素,因此当加入新的元素时,需要用push_back()/insert()函数。
resize是改变容器的大小,并且创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。
再者,两个函数的形式是有区别的,reserve函数之后一个参数,即需要预留的容器的空间;resize函数可以有两个参数,第一个参数是容器新的大小,第二个参数是要加入容器中的新元素,如果这个参数被省略,那么就调用元素对象的默认构造函数。

[https://blog.csdn.net/colddie/article/details/8665456]

九、容器操作函数push_back和insert的区别

都是STL中容器的操作函数,
顾名思义push_back把元素插入容器末尾,insert把元素插入任何你指定的位置。
不过push_back速度一般比insert快。如果能用push_back尽量先用push_back

十、assert

assert宏的原型定义在<assert.h>中,其作用是如果它的条件返回错误,则终止程序执行。
原型定义:

#include <assert.h>
void assert( int expression );

assert的作用是先计算表达式 expression ,如果其值为假(即为0),那么它先向stderr打印一条出错信息,然后通过调用 abort 来终止程序运行。

十一、NULL与0的区别、nullptr的来历

[https://www.cnblogs.com/malecrab/p/5569707.html]
根本原因就是:常数0既是整数常量,也是空指针常量。
为了解决这种二义性,C++11标准引入了关键字nullptr,它作为一种空指针常量。

十二、C++中异常处理语句exit(0)、exit(1)和exit(-1)有什么区别?

exit为C++的退出函数,声明于stdlib.h中,对于C++其标准的头文件为cstdlib,声明为
void exit(int value);
exit的功能为,退出当前运行的程序,并将参数value返回给主调进程。
在main中return v;的效果 与exit(v);相同。
exit(1)和exit(-1)
是分别返回1和-1到主调程序。
exit(0)则是返回0。
exit(0)表示程序正常退出,非0表示非正常退出

十三、关键字friend

原则上, 类的私有(private)和受保护(protected)成员不能从声明它们的同一类外部访问。但是, 此规则不适用于友元 "friends"。
友元函数是可以直接访问类的私有成员的非成员函数。它是定义在类外的普通函数,它不属于任何类,但需要在类的定义中加以声明,声明时只需在友元的名称前加上关键字friend。
使用友元类时注意:
  1、友元关系不能被继承。
  2、友元关系是单向的,不具有交换性。若类B是类A的友元,类A不一定是类B的友元,要看在类中是否有相应的声明。
  3、友元关系具有非传递性。若类B是类A的友元,类C是B的友元,类C不一定是类A的友元,同样要看类中是否有相应的申明。

十四、enum

[https://www.runoob.com/w3cnote/cpp-enum-intro.html]

十五、unsigned

无符号数,作用为存储的数据范围大
unsigned char是无符号字节型,char类型变量的大小通常为1个字节(1字节=8个位),且属于整型。整型的每一种都有无符号(unsigned)和有符号(signed)两种类型(float和double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(char有点特别),如果需声明无符号类型的话就需要在类型前加上unsigned。无符号版本和有符号版本的区别就是无符号类型能保存2倍于有符号类型的数据,比如16位系统中一个int能存储的数据的范围为-3276832767,而unsigned能存储的数据范围则是065535。
malloc函数是分配内存空间函数,参数是待分配的类型在内存中所占的字节数
例如,二进制数 1000 0001
有符号术是-1,无符号数是129.就是第一位为1时,无符号数把它当数位,而有符号数把他当负号

十六、C++ public、protected 、 private和friend

[https://blog.csdn.net/a3192048/article/details/82191795]

十七、const和static的区别

const定义的常量在超出其作用域之后其空间会被释放,而static定义的静态常量在函数执行后不会释放其存储空间。

十八、virtual(虚函数)的用法

虚函数最关键的特点是“动态联编”,它可以在运行时判断指针指向的对象,并自动调用相应的函数。.
[https://www.cnblogs.com/weiyouqing/p/7544988.html]

十九、static_cast dynamic_cast reinterpret_cast const_cast

static_cast

用法:static_cast < type-id > ( exdivssion )

该运算符把exdivssion转换为type-id类型,但没有运行时类型检查来保证转换的安全性。

dynamic_cast

用法:dynamic_cast < type-id > ( exdivssion )

该运算符把exdivssion转换成type-id类型的对象。Type-id必须是类的指针、类的引用或者void *;
如果type-id是类指针类型,那么exdivssion也必须是一个指针,如果type-id是一个引用,那么exdivssion也必须是一个引用。

reinterpret_cast

用法:reinterpret_cast (exdivssion)

reinterpret_cast运算符是用来处理无关类型之间的转换;它会产生一个新的值,这个值会有与原始参数(expressoin)有完全相同的比特位。按照reinterpret的字面意思“重新解释”,即对数据的比特位重新解释。

const_cast

用法:const_cast (exdivssion)

该运算符用来修改类型的const、volatile、__unaligned属性。除了const 、volatile、__unaligned修饰之外, type_id和exdivssion的类型是一样的。
常量指针被转化成非常量指针,并且仍然指向原来的对象;
常量引用被转换成非常量引用,并且仍然指向原来的对象;常量对象被转换成非常量对象。

总结

类指针或引用的上行转换static_cast 和 dynamic_cast 都可以
类指针或引用的下行转换用dynamic_cast并且判断转换后是否为空
基本数据类型之间的转换用static_cast, 但是由于数值范围的不同,需要用户保证转换的安全性
不同类型之间的指针或引用的转换用reinterpret_cast,它的本质是对指向内存的比特位的重解释
消除数据的const、volatile、__unaligned属性,用const_cast

二十、inl文件介绍

inl文件是内联函数的源文件。内联函数通常在C++头文件中实现,但是当C++头文件中内联函数过多的情况下,我们想使头文件看起来简洁点,能不能像普通函数那样将内联函数声明和函数定义放在头文件和实现文件中呢?当然答案是肯定的,具体做法将是:将内联函数的具体实现放在inl文件中,然后在该头文件末尾使用#include引入该inl文件。
由于编译器等不支持将模板函数、模板类等放单独分开编译,但是有了inl文件,我们可以把声明放在头文件中,然后将具体实现放在inl文件中。
对于比较大的工程来说,出于管理方面的考虑,模板函数、模板类的声明一般放在一个或少数几个头文件中,然后将其定义部分放在inl文件中。这样可以让工程结构清晰、明了。

二十一、函数名后加const

class MyClass  
{   
  public:   
      int GetData(int Id,int Type,char* pData)const;  
}  

通过把类成员函数声明为const 以表明它们不修改类对象。
任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误,这样做的好处是提高程序了的健壮性。

二十二、auto关键字的使用

auto可以在声明变量的时候根据变量初始值的类型自动为此变量选择匹配的类型,类似的关键字还有decltype。
这种用法就类似于C#中的var关键字。auto的自动类型推断发生在编译期,所以使用auto并不会造成程序运行时效率的降低。而是否会造成编译期的时间消耗,我认为是不会的,在未使用auto时,编译器也需要得知右操作数的类型,再与左操作数的类型进行比较,检查是否可以发生相应的转化,是否需要进行隐式类型转换。

适用情况

  1. 用于代替冗长复杂、变量使用范围专一的变量声明。
    2.在定义模板函数时,用于声明依赖模板参数的变量类型。
    3.模板函数依赖于模板参数的返回值

[https://www.cnblogs.com/KunLunSu/p/7861330.html]

二十三、set的用法

set的特性是,所有元素都会根据元素的键值自动排序,set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值,实值就是键值。set不允许两个元素有相同的键值。

[https://www.cnblogs.com/caiyishuai/p/8646345.html]

二十四、Linux中.swp 文件的产生与解决方法

[https://blog.csdn.net/qq_42200183/article/details/81531422]

二十五、%g格式输出

%g用来输出实数,它根据数值的大小,自动选f格式或e格式(选择输出时占宽度较小的一种),且不输出无意义的0。即%g是根据结果自动选择科学记数法还是一般的小数记数法
对于指数小于-4或者大于给定精度的数值,按照%e的控制输出,否则按照%f的控制输出.

二十六、当只应用了"gui.h"的某个函数时,可以直接include该函数需要的头文件即可

如,QMutex(Qt Core5.15.3)
bing.com 国际版搜索QMutex,找到相应的QT版本号,
include搜索到的Header即可
[https://doc.qt.io/qt-5/qmutex.html]

二十七、直接找函数定义的类位置而不是namespace位置(namespace可能有多个同名的)

二十八、继承类的函数本类找不到去父类找

二十九、调用类函数


可以如此调用: CellTypeWrapper().getTypeName

三十、对象和指针的相互转换关系

#include <iostream>
#include <string>
 
using namespace std;
 
int main(){
 
    string str = "abc";
    string *ps;
    ps = &str;  //把 str对象的地址赋值给指针ps
    cout<<*ps<<endl;  //这就是把指向string对象的指针对其'解引用'转换为对象str. 
                                //结果输出 abc
}

一个坑

.h
at::Tensor* supply_;
.cc
supply_ = new at::Tensor;
supply_ = &(at::zeros({fpga->nx(), fpga->ny(), kDirAll}));      // 错误  **临时对象的地址引用是不可靠的**
.h
at::Tensor* supply_;
.cc
supply_ = new at::Tensor;
*supply_ = at::zeros({fpga->nx(), fpga->ny(), kDirAll});      // 正确  **给指针对象赋值**

三十一、使用std::函数时,注意传参类型

如const char*的情况,尤其要注意const的使用及c_str()的使用

三十二、判断某浮点数x为nan(not a number)

if (x != x) return true;

三十三、namespace里函数的两种调用形式

https://www.runoob.com/cplusplus/cpp-namespaces.html

namespace A{
  void xx();
}
1.
namespace B{
  A::xx();
}
2.
using namespace A;
namespace B{
  xx();
}

另,或许需要在最早进入的函数所在的A.cc做个声明

namespace A{
  clss a;
}

其中,A在B.cc或B.h进行了定义

namespace A{
  class a{
  };
}

三十四、ifndef/define/endif的作用

此篇讲的很详细:https://blog.csdn.net/baidu_27690801/article/details/95016120

1.作用:防止头文件被重复包含和编译
2.缺失ifndef的风险:a.重复定义 b.无限循环编译
3.建议:所有头文件前后都加上ifndef/define/endif

三十五、巨坑!!!

std::vector<Master> masters() { return masters_; }
std::vector<Master
>& masters() { return masters_; }

两者的区别:
前者是copy,后者是reference
若返回的成员变量比较大时,会浪费大量的时间导致rls和dbg的不一致(时间上)
另外,
最好加上const,防止外界不必要的改动

三十六、友元函数

类A有protected的static函数a
函数B想静态调用函数a,只需要将函数B声明为类A的友元函数即可

三十七、返回私有变量函数写法

const std::vector<>&

三十八、判断奇偶

if (i & 1) {
奇数
} else {
偶数
}

三十九、error use of deleted function in c++

[https://blog.csdn.net/creambean/article/details/91899567]

一般来说, 该错误大致都是编译器认为默认构造函数有问题时, 不提供默认构造函数造成的.
当然, 如果自己显示的使用delete关键字, 也会报该错误

解决:
解决方法就是显示的提供一个合适的构造函数即可.

四十、百分比打印

Log::print("\tchain_len: %d = %d / %d [%2.2lf\%]\n", lc.first, lc.second, tn.second.size(), static_cast<float>(lc.second * 100) / static_cast<float>(tn.second.size()));

四十一、二维vector初始化

std::vector<std::vector<int> > num_dists(4, std::vector<int>(20, 0));

四十二、去除dirty数据

同一个变量在不同阶段有不同赋值
若阶段中间没有用到,记得在每个阶段后清空。

四十三、替换文件的时候用cp不要用mv

编译器发现文件名相同的时候会默认已编译过 导致改动部分不参与编译

四十四、undefined reference to 构造函数/析构函数

构造函数或析构函数没有实现
right:
~Record(){};
error:
~Record();

四十五、把带有默认值的参数放到最后

四十六、auto和auto&


切记reference的问题

四十六、类A里有返回值为类B的函数

类B要在类A前面声明

四十七、external

C对A、B分别调用C时需做出不同反馈
可在头文件声明external变量
在A、B文件中赋予变量不同值以标识
声明:

定义:

赋值及调用:





四十八、const关键词在函数声明不同位置的区别

const lecompiler::Geometry::Rect getBound() const { return _boundary; }
容易报错如下:
error: passing ‘const xxx’ as ‘this’ argument of ‘std::string xxx()’ discards qualifiers [-fpermissive]
错误原因为:
C++中const 引用的是对象时只能访问该对象的const 函数,因为其他函数有可能会修改该对象的成员,编译器为了避免该类事情发生,会认为调用非const函数是错误的。
意思是说 在一个加了const限定符的成员函数中,不能够调用非const成员函数。而error:…discards qualifiers 的意思就是缺少限定符。
解决方法:
给成员函数加上const,或者去掉该函数的前缀关键词const如下:
lecompiler::Geometry::Rect getBound() const { return _boundary; }
此处的const目的为返回值不可修改
[https://blog.csdn.net/WhereYouSink/article/details/125852370]

四十九、正则匹配在线检测:

https://regex101.com/

五十、程序抛出异常导致的没有正常执行代码问题


求助一下大家... 有没有谁遇到这种程序有自己想法的情况啊?这个函数进来了,但是并不执行后续任何行为就跳出去了,然后后续又继续执行了,等循环下一次还能进来,但是依然不执行后续操作莫名其妙就跳过了...
throw了

catch到一些错误,可能是这些错误导致这个函数没有正常执行

五十一、多线程

async比thread pool內存增量小

五十二、智能指针和普通指针的转化

cell为对象
std::shared_ptr<lecompiler::PhyService::Cell>(&cell)
错误,只能用普通指针&cell,不可强转为智能指针

五十三、内存优化

posted @ 2019-05-26 10:19  HKSun  阅读(313)  评论(0编辑  收藏  举报