c/c++
文章平均质量分 54
The Goat
God of coding
展开
-
c++浅探类内存布局
总结多重继承和虚继承不用了解太多,现实中不怎么用到。对单继承若父类和子类都没有虚函数,则子类对象的内存布局没有虚表指针和虚表,只有成员变量的内存(字节需要对齐),且父类成员在内存低地址,子类额外的成员在内存高地址(因此,子类指针可以转换为父类指针,又可以再次转换为子类指针,因为子类对象的内存中低地址为父类的成员变量)若父类有虚函数,则子类对象的内存布局起始地址部分为虚表指针,指向虚表,后面的结构同上。虚表里面,包含了父类和子类的虚函数,若子类覆盖了父类的虚函数,则子类的虚函数在子类的虚表里面。在构原创 2021-01-05 14:50:08 · 118 阅读 · 0 评论 -
c++优先级队列访问元素方法
stl提供的优先级队列priority_queue,功能很少,主要是没法通过下标或者迭代器访问元素,只能不停地pop元素去逐一访问,非常难用。如何访问优先级队列的元素?方法1,继承c++ stl优先级队列(c++优先级队列内部使用的sequence成员的访问级别是protected,在你的子类中可以把该sequence的迭代器开放出来,达到访问元素目的)方法2,可以利用multimap实现优先级队列,能做到:自定义key比较器相比普通map,multimap允许key重复mult原创 2020-12-31 15:04:45 · 1874 阅读 · 0 评论 -
c++ std::stringstream清除字符串
stringstream.str()会返回其内部字符串的拷贝。有时候,想清空stringstream内部的字符串内容,真确的清理方式是:stringstream.str(std::string());stringstream.clear();其中,stringstream.str(std::string())的作用是清空stringstream内部的字符串内容,stringstream.clear()的作用是将该流中所有的状态位复位,将流的状态设置为有效。这一句也很关键,这是因为当流发生错误后,原创 2020-12-14 20:48:15 · 3941 阅读 · 0 评论 -
c++虚函数表知识点
参考:理解 C++ 虚函数表类的普通函数(非虚函数),在内存中地址是唯一的,可以把他们想象成普通函数,只不过第一个参数是this指针,在通过类对象指针调用时,编译器会根据类型找到相应的非虚函数的地址,这个工作是编译期完成的每个类都会维护一个虚表,编译时,编译器根据类的声明创建出虚表,对象被构造时,虚表的地址就会被写入到这个对象内存的起始位置。父类、子类的虚表是不同的,虚表里面的内容也是不一样的(虚表里面记录了要执行的函数的函数指针)。虚函数在执行是一个动态的过程,并不是在编译时就确定下来要执行哪一个函原创 2020-11-16 14:05:56 · 202 阅读 · 0 评论 -
c/c++ pod类型介绍
一、啥是pod类型pod:plain old data,是 C++ 定义的一类数据结构概念,比如 int、float 等都是 POD 类型的。Plain 代表它是一个普通类型,Old 代表它是旧的,与几十年前的 C 语言兼容,那么就意味着可以使用 memcpy() 这种最原始的函数进行操作。基本上谈到这个概念,一般都是说某某 class、struct、union 是不是 POD 类型的。二、pod的特征要求有两个:一个是它必须很平凡、很普通;另一个是布局有序。平凡数据类型拥有平凡的默认构造原创 2020-07-29 15:44:35 · 4619 阅读 · 3 评论 -
GCC likely和unlikely(__builtin_expect)的作用
在Linux2.6内核中,看到一对奇怪的函数,likely(), unlikely()。追踪回去,发现其实是一对宏,如下实现:#define likely(x) __builtin_expect((x), 1)#define unlikely(x) __builtin_expect((x), 0)查了一下是这样说的:例如:if( likely(val)) if( unlikely (val))他们都等于if(val),也就是在理解上来说,是等价的。那么为什么要这样用呢?__原创 2020-07-10 14:44:15 · 1933 阅读 · 0 评论 -
c++程序链接阶段:undefined reference to xxx function(未定义引用问题)原因解析
问题分析c++程序,在链接阶段,当你的程序引用了第三方库中定义的函数时(程序内部定义的函数不涉及这个问题,因为函数的实现已经在自己的代码段、数据段中了),连接器会在三方库中搜索当前符号表中未定义的符号(这些未定义的符号需要在三方库中定位到,否则就会出现对xxx函数未定义引用),当在三方库的符号表中找不到对应的符号时,就会报undefined reference to xxx function。注意,当遇到这个问题时,首先要排除是否三方库有没有被正确链接。当三方库没有被正确链接时,报的错误通常是“can原创 2020-06-28 11:52:34 · 4022 阅读 · 0 评论 -
利用c++/opencv读取并显示raw图像
raw图像,opencv的imread不支持直接读入,但可以通过c++的ifstream读入。注意的一点是,读取时,mode要设置成std::ios::binary,即把raw图像当做二进制文件读入。读取后,构造opencv mat,并显示出来,代码如下: // open raw data const std::string file_path = "/home/zhangshan/image/image.raw"; std::ifstream fin; // 注意,这里要原创 2020-06-09 11:06:31 · 8341 阅读 · 3 评论 -
c/c++依赖静态库、动态库符号问题
一些结论:liba.so / liba.a对应cppint subfunc(int a, int b) { return a + b; } int funcA(int a, int b) { return subfunc(a, b); }符号信息liba.so: func_sub, func_alibB.so / ...原创 2020-04-29 13:47:47 · 3556 阅读 · 1 评论 -
c++11 最简单的线程安全的单例模式(利用local static)
C++11规定了local static在多线程条件下的初始化行为,要求编译器保证了内部静态变量的线程安全性。在C++11标准下,《Effective C++》提出了一种更优雅的单例模式实现,使用函数内的 local static 对象。这样,只有当第一次访问getInstance()方法时才创建实例。这种方法也被称为Meyers’ Singleton。C++0x之后该实现是线程安全的,C++0x...原创 2020-04-28 11:44:02 · 5168 阅读 · 0 评论 -
[转]宏的高级使用 #, ##, __VA_ARGS__, __FILE__, __FUNCTION__
文章目录一 常见宏概念二 常见宏的使用1.字符串化```#```2.宏连接符```##```3.宏变量解析重点:编译过程一 常见宏概念先说一下本文中会提到的内容:#,##,__VA_ARGS__, __FILE__, __LINE__ , __FUNCTION__等#: 把语言符号转换成字符串 ,字符串化(stringizing)##: 宏连接符__VA_ARGS__:...原创 2020-04-15 11:22:10 · 222 阅读 · 0 评论 -
valgrind检查c/c++程序内存问题
简介:Valgrind 可以用来检测程序是否有非法使用内存的问题,例如访问未初始化的内存、访问数组时越界、忘记释放动态内存等问题。实战:valgrind --tool=memcheck --leak-check=full --vex-guest-max-insns=25 --show-leak-kinds=all -v --log-file="memcheck.txt" 解释下--ve...原创 2020-04-14 20:05:03 · 304 阅读 · 0 评论 -
c++ unique_ptr作为函数参数
参考:https://stackoverflow.com/questions/22064103/c-unique-ptr-constant-reference如果函数不需要所有权,不要传unique_ptr的引用,而是传一个普通引用,例如例子中的那样。...原创 2020-01-19 19:10:21 · 6445 阅读 · 0 评论 -
C++ 关于enum的一些知识点
enum主要分为非限定作用域(不带class)和限定作用域这两种。enum xxx {…} // 非限定作用域,枚举中每个成员的作用域和枚举对象相同。enum class xxx {…} // 限定作用域,枚举中每个成员的作用域在作用域中,枚举类型作用域外不可访问。不限定作用域的枚举类型的枚举成员可以自动转换成int,限定作用域不会。int如何转换成枚举?https://...原创 2020-01-19 17:28:44 · 312 阅读 · 0 评论 -
[转]基于C++11的线程池(threadpool),简洁且可以带任意多的参数
参考:基于C++11的线程池(threadpool),简洁且可以带任意多的参数本人解读:用一个vector保存N个线程,这个vector就成了一个线程池。每个线程,都会通过一个while(!stop)的循环,轮寻task,当有task来临时,就会执行task。当没有task时,线程会wait,阻塞住,等待task来临。task有一个队列,每当新task来临时,会入队,同时,会noti...原创 2020-01-19 16:58:12 · 326 阅读 · 0 评论 -
C++ Primer 第3章 知识点回顾
3.2.2 string对象上的操作在执行读取操作时,string对象会自动忽略开头的空白(即空格符、换行符、制表符等)从第一个真正的字符开始读起,直到遇见下一个空白为止。getline(cin,str)//读取一整行,遇到换行符结束。把换行符也读进来了,但是没有保存到str中3.5.1 定义和初始化内置数组数组的维度必须是一个常量表达式,默认情况下,数组的元素被默认初始化int *(&a原创 2016-08-03 21:24:24 · 320 阅读 · 0 评论 -
C++ Primer 第17章 知识点回顾
17.1 tuple类型17.2 bitset类型17.4.1 随机数引擎和分布引擎类型、分布类型default_random_engine e; cout<<e()<<endl;uniform_int_distribution<unsigned> u(0, 9);//指定分布类型 default_random_engine e; //将u作为随机数源 //每个调用返回在指定范围内并服从原创 2016-08-12 21:31:00 · 352 阅读 · 0 评论 -
C++ Primer 第18章 知识点回顾
18.1 处理异常异常对象用来初始化catch的参数异常声明的静态类型将决定catch语句所能执行的操作18.2 命名空间命名空间作用域后面无须分号 2. 对于命名空间中名字的隐藏规则来说有一个重要的例外,它是的我们可以直接访问输出运算符。这个例外是,当我们给函数传递一个类类型的对象时,除了在常规的作用域查找外还会找实参类所属的命名空间。这一例外对于传递类的引用或指针的调用同样有效在函原创 2016-08-13 12:26:08 · 304 阅读 · 0 评论 -
C++ Primer 第19章 知识点回顾
19.1控制内存分配new过程:一、operator new标准库函数,分配原始未构造内存;二、编译器运行相应构造函数;三、返回指针operator delete释放内存空间定位new: new (place_address) type (initializers),定位new允许我们在一个特定的。预先分配的内存地址上构造对象 1. 定位new与allocator的construct成员非常原创 2016-08-13 17:26:20 · 405 阅读 · 0 评论 -
数组名和指针的区别
指针和数组名的共同特点是都是用来指代一个地址的。不同的是:1、指针是需要占用内存空间来存储地址的;数组名则更像是一个立即数或者常数。你可以修改指针指向的内容,但你绝对无法改变数组名的指向。2、数组和指针对于sizeof来说是不同的,指针变量占用的空间通常等于当前CPU的最大位数,数组名取sizeof的话,得到的则是数组的大小。3、如果用extern声明一个外部变量,指针和数组不能混用。比如在文件1.原创 2019-07-22 09:56:11 · 1120 阅读 · 0 评论 -
c++11 多线程类std::thread/std::mutex等知识点总结
c++11从语言层面把多线程引入了标准库,相比其他多线程库,c++11语言层面的多线程库具备优秀的跨平台能力,值得C++程序员了解下。关于多线程,常见的知识主要包括:锁(互斥锁、读写锁等)条件变量信号量等等网络上关于c++11多线程的博文很多,这里主要参考的是:https://www.cnblogs.com/haippy/p/3284540.html这个系列主要翻译C++官方文...原创 2019-08-26 19:48:43 · 312 阅读 · 0 评论 -
C++ Primer 第16章 知识点回顾
16.1.1 函数模板非类型模板参数:用户提供的值必须是常量表达式,从而允许编译器在编译时实例化模板在模板定义内,模板非类型参数是一个常量值,在需要常量表达式的地方,可以使用非类型参数,例如指定数组的大小模板程序应该尽量减少对实参类型的要求函数模板与类模板成员函数的定义通常放在头文件中。而类成员函数和普通函数的定义通常放在源文件,同时类定义和函数声明放在头文件中16.1.2 类模板与函数原创 2016-08-12 10:01:05 · 269 阅读 · 0 评论 -
C++ Primer 第6章 知识点回顾
6.1.1 局部对象如果局部静态变量没有显式的初始值,它将执行值初始化。内置类型的局部静态变量初始化为06.2.3 const形参和实参形参的顶层const被忽略掉了,故void fcn(const int i);void fcn(int i);表示同一个函数,不会构成重载6.2.4 数组形参int (&arr)[10]c++允许将变量定义成数组的引用,此时,引用形参绑定到对应的实参上,也原创 2016-08-04 22:17:58 · 313 阅读 · 0 评论 -
C++ Primer 第5章 知识点回顾
5.3.2 switch语句switch语句计算一个整型表达式的值,然后根据这个值从几条执行路径中选择一条。case关键字和她对应的值被一起称为case标签,case标签必须是整型常量表达式5.5.4 do while语句condition不能为空,condition使用的变量必须定义在循环体之外,不允许在条件部分定义变量原创 2016-08-04 14:51:30 · 249 阅读 · 0 评论 -
C++ Primer 第4章 知识点回顾
4.2 算术运算符(-m)/n和m/(-n)都等于-(m/n),m%(-n)等于m%n,(-m)%n等于-(m%n)4.3 逻辑和关系运算符进行比较运算时除非比较的对象是布尔类型,否则不要使用布尔字面值true和false作为运算对象&&、||、条件运算符、逗号运算符规定了求值顺序,对于没有规定运算对象求职顺序的运算符,可能产生未定义行为4.8 位运算符& 、|、~重载运算符的优先级和原创 2016-08-04 10:32:13 · 388 阅读 · 0 评论 -
C++ Primer 第2章 知识点回顾
2.3.1 引用引用必须被初始化引用并非对象,不能定义引用的引用引用只能绑定到对象上,而不能与字面值或某个表达式的计算结果绑定在一起2.3.2 指针因为引用不是对象,没有实际地址,所以不能定义指向引用的指针预处理器是运行于编译过程之前的一段程序,当用到一个预处理变量时,预处理器会自动的将它替换为实际值引用本身不是一个对象,因此不能第一指向引用的指针。但指针是对象,所以存在对指针的引用原创 2016-08-02 23:12:41 · 339 阅读 · 0 评论 -
C++ Primer 第7章 知识点回顾
7.1 定义抽象数据类型定义在类内部的函数是隐式inline函数成员函数通过一个名为this的额外的隐式形参来访问调用它的那个对象。当我们调用一个成员函数时,用请求该函数的对象地址初始化this,例如total.isbn()则编译器负责吧total的地址传递给isbn的隐式形参this。因为this的目的总是指向“这个”对象,所以this是一个常量指针,我们不允许改变this中保存的地址。常量原创 2016-08-05 17:07:28 · 455 阅读 · 0 评论 -
C++ Primer 第8章 知识点回顾
暂时无原创 2016-08-05 18:55:38 · 204 阅读 · 0 评论 -
C++ Primer 第9章 知识点回顾
9.2.3 begin和end成员实际上有两个名为begin的成员,一个是const成员,返回const_iterator,另一个是非常量成员,返回iterator,构成重载auto it=a.begin();//仅当a是const,it是const_iterator;9.2.4 定义和初始化只有顺序容器的构造函数才接受大小参数,关联容器并不支持将一个容器初始化为另一容器的拷贝:接受迭代器范原创 2016-08-06 10:52:51 · 238 阅读 · 0 评论 -
C++ Primer 第15章 知识点回顾
15.2.1 定义基类派生类可以继承定义在基类中的成员,但是派生类的成员函数不一定有权访问从基类继承而来的成员。和其他使用基类的代码一样,派生类能访问公有成员,而不能访问私有成员。15.2.2 定义派生类声明派生类,声明中更包含类名但是不能包含它的派生类列表class NoDerived final {/*..*/}//防止继承15.3 虚函数所有虚函数都必须有定义把某个函数指定为fi原创 2016-08-10 20:51:22 · 420 阅读 · 0 评论 -
C++ Primer 第14章 知识点回顾
14.1 基本概念通常情况下,不应该重载逗号,取地址,逻辑与,逻辑或运算符重载运算符至少含有一个类类型的参数。14.2.1 重载输出运算符<<ostream& operator<<(ostream& os,const Sales_data& item);通常,输出运算符应该主要负责打印对象的内容而非控制格式,输出运算符不应该打印换行符IO运算符通常需要读写类的非公有数据成员,所以IO运算原创 2016-08-09 21:15:37 · 369 阅读 · 0 评论 -
C++ Primer 第13章 知识点回顾
13.1.1 拷贝构造函数直接初始化:根据参数选择最匹配的构造函数拷贝初始化:使用拷贝构造函数或移动构造函数来完成,要求编译器将右侧运算对象拷贝到正在创建的对象中,如果需要的话还要进行类型转换Foo(const Foo&);//声明拷贝构造函数有explicit构造函数的对象只能使用直接初始化如果我们没有为一个类定义拷贝构造函数,编译器会为我们定义一个。即使我们定义了其他构造函数,编译器也原创 2016-08-08 22:23:31 · 469 阅读 · 0 评论 -
C++ Primer 第12章 知识点回顾
静态内存(局部static对象,类static成员,全局变量)、栈内存(函数内非static变量)、堆(也叫自由空间,存储动态分配的对象,即运行时分配)。动态对象生存期由程序来控制,其他对象由编译器自动创建和销毁。12.1.1 shared_ptr类程序使用动态内存处于一下三种原因之一: 程序不知道自己需要使用多少对象程序不知道所需对象的准确类型程序需要在多个对象间共享数据12.1.2 直原创 2016-08-07 19:35:17 · 482 阅读 · 5 评论 -
C++ Primer 第11章 知识点回顾
11.2.2关键字类型的要求在实际编程中,重要的是,如果一个类型定义了“行为正常”的<运算符,则他可以用作关键字类型。用来组织一个容器中元素的操作的类型也是该容器类型的一部分,为了指定使用自定义的操作,必须在定义关联容器类型是提供此操作的类型。自定义的操作类型必须在尖括号中紧跟元素类型给出 //定义了比较函数,比较操作类型应该是一种函数指针类型 multiset<Sales_data,dec原创 2016-08-07 11:41:43 · 485 阅读 · 0 评论 -
C++ Primer 第10章 知识点回顾
10.2.2 写容器元素的算法我们常常使用back_inserter来创建一个迭代器,作为算法的目的位置来使用fill_n(back_inserter(vec),10,0);(每次赋值都会在vec上调用push_back),使用back_inserter按需要增长目标序列10.2.3 重排容器元素的算法标准库算法对迭代器而不是容器进行操作,因此,算法不能直接添加或删除元素10.3.1 向算法原创 2016-08-06 20:58:31 · 302 阅读 · 0 评论