C++
五山口老法师
腾讯后台开发工程师
展开
-
C++ :extern
==条款1:避免把#include指令放在extern "C"里面== 不知道在你工作过的系统里,能够看到多少类似下面的代码:{{{#ifndef __MY_HANDLE_H__#define __MY_HANDLE_H__}}}{{{#ifdef __cplusplusextern "C" {#endif}}}{{{#include <typedef.h>#include <errcode.h>}}}{{{typedef void* my_h.原创 2021-04-15 10:44:41 · 952 阅读 · 0 评论 -
linux gcc编译错误:statically linked applications requires at runtime the shared libraries
statically linked applications requires at runtime the shared libraries from the glibc version used for linking。此错误是因为gcc编译选项中有static相关参数,此参数禁止gcc编译时使用动态库,即使-lXXXX也不行。此时,把此static选项去掉程序即可通过编译...原创 2021-03-29 19:41:14 · 5480 阅读 · 3 评论 -
指定结构体字节对齐方式
指定结构体字节对齐方式#pragmapack(push,1)typedefstruct{intb;chara;}struct_t1;#pragmapack(pop)原创 2020-12-31 11:01:42 · 315 阅读 · 0 评论 -
C++11中Thread类简单使用的例子
代码如下:#include <iostream>#include <thread>#include <chrono>#include <future>#include <cmath> #include <vector>#include <cstdlib>using namespace std;void helloworld() { cout << "hello world" <&l原创 2020-07-30 15:52:08 · 537 阅读 · 0 评论 -
Thread中,join()方法
std::thread是c++11新引入的线程标准库,通过其可以方便的编写与平台无关的多线程程序,虽然对比针对平台来定制化多线程库会使性能达到最大,但是会丧失了可移植性,这样对比其他的高级语言,可谓是一个不足。终于在c++11承认多线程的标准,可谓可喜可贺!!!在使用std::thread的时候,对创建的线程有两种操作:等待/分离,也就是join/detach操作。join()操作是在std::thread t(func)后“某个”合适的地方调用,其作用是回收对应创建的线程的资源,避免造成资源的泄露。d原创 2020-07-30 14:17:40 · 796 阅读 · 0 评论 -
45.赋值运算符
我们在一个类里面重载赋值运算符的时候,有:拷贝赋值运算符,移动赋值运算符,以initializer_list为参数的赋值运算符,复合赋值运算符。复合赋值运算符不得非要是类的成员,不过我们倾向于将所有的赋值运算符包含在类的内部。拷贝赋值运算符,移动赋值运算符 要考虑自赋值情况。 以initializer_list为参数的赋值运算符strvec & strvec::...原创 2018-10-21 11:09:02 · 212 阅读 · 0 评论 -
46.一个例子了解C++中异常处理
异常处理的栈展开、析构函数和构造函数的异常,异常处理的层次catch的搜索匹配 。。。class wrong :public exception{public: wrong(const int& i = 0,const string& str = ""):err_no(i),err_str(str){} string what() { cout <&l...原创 2018-10-25 22:09:46 · 186 阅读 · 0 评论 -
简单了解一下函数模板
泛型编程的基础就是模板的使用。在编写函数模板的时候有许多需要注意的点。我们使用一个栗子轻松搞定。using namespace std;template<class T, typename U> inlineU func(T & t, U& u);template<class T, typename U> inlineU func...原创 2018-10-23 20:00:17 · 158 阅读 · 0 评论 -
47.命名空间namespace
每个命名空间就是一个作用域。命名空间是不连续的,存在则追加,不存在则创建。内联命名空间,可以使得最外层的命名空间直接使用内层任何一层的成员名字,而无需添加中间层的命名空间的名字。未命名的命名空间中定义的成员具有静态生命周期,声明时创建,程序结束时销毁。内层未命名的命名空间可以直接使用外层命名空间的名字直接访问成员。命名空间的别名namespace abcdefj{vo...原创 2018-10-27 19:31:35 · 183 阅读 · 0 评论 -
48.聊一聊constexpr变量
常量表达式,是指值不会变并且在编译的时候就已经能够计算出结果的表达式。字面值属于常量表达式,用常量表达式初始化的const变量也是常量表达式。一个对象是或不是常量表达式,要根据他的数据类型和初始值共同决定!int a = 42;const int b = size();上面的a和b都不是常量表达式!不过b要想是常量表达式的话只要满足size()是constexpr函数就行! ...原创 2018-11-05 21:22:17 · 306 阅读 · 0 评论 -
38.C++修饰构造函数的explicit关键字
C++ explicit关键字的作用主要是用来修饰类的构造函数,表明该构造函数是显式的,禁止单参数构造函数的隐式转换。如果C++类的构造函数有一个参数,那么在编译的时候就会有一个缺省的转换操作:将该构造函数对应数据类型的数据转换为该类对象,如下面所示:class MyClass{public: MyClass(int num);}MyClass obj = 10; //ok, co...原创 2018-10-17 20:05:20 · 162 阅读 · 0 评论 -
37.拷贝控制和资源管理
类中只要有一个成员不可能拷贝、赋值、析构的话,类的合成拷贝控制成员就被定义为delete在新标准发布之前,要想阻止拷贝,类将拷贝构造函数和拷贝赋值运算符声明为private,只是声明,没有给出定义。这样一来,试图拷贝对象的用户代码在编译阶段就会被标记为错误。成员函数或者友元函数中的拷贝操作将会导致链接时错误。定义行为像值的类当我们拷贝一个像值的对象时,副本和原对象是完全独立的。改变...原创 2018-10-16 21:23:06 · 165 阅读 · 0 评论 -
44.移动迭代器
普通迭代器解引用后返回一个指向元素的左值。移动迭代器解引用之后返回右值引用。将一个普通迭代器转化为移动迭代器使用函数 make_move_iterator ,它接受一个普通迭代器参数,返回一个右值引用!...原创 2018-10-19 09:47:35 · 348 阅读 · 0 评论 -
24.指针和引用的区别
在面试时经常会被问到 指针和引用的区别,虽然问题很简单但还是总结一下!指针和引用的区别其实有太多了,主要的区别大概是这样子:1)指针声明的时候可以不被初始化(有可能成为野指针),但是引用必须要进行对象的绑定;2)引用作为一个对象别名,而指针却是一个存有对象地址的变量。3)指针是对象,可以被声明为常量;引用不是对象。4)sizeof作用于指针得到4字节,作用于引用得到的是对象的大...原创 2018-10-09 22:32:03 · 320 阅读 · 0 评论 -
36.需要析构函数的类也需要拷贝和赋值操作
当一个类需要定义自己版本的析构函数的时候,一般就是在类对象的创建过程中使用了动态内存。一旦使用了动态内存,就会涉及深浅拷贝的问题。我们知道,默认拷贝构造函数执行的是浅拷贝,这就会引起一份内存被释放两次,会出错。因此,我们会就需要定义自己版本的构造函数和赋值运算符!...原创 2018-10-15 22:23:28 · 370 阅读 · 0 评论 -
34.动态数组
new和delete运算符一次只分配/释放一个对象,但是某些应用需要以此为很多对象分配内存的功能。C++中制定了两种分配/释放多个对象的机制!分别是:new[]/delete[] 和 allocator类。其中new[]/delete[]再分配内存的时候就初始化对象;allocator类将内存的分配和对象的初始化分离。类似于预加载和懒加载。new[]的初始化int *...原创 2018-10-15 21:01:28 · 158 阅读 · 0 评论 -
49.函数指针那些事儿
函数指针原创 2018-11-05 21:35:41 · 134 阅读 · 0 评论 -
C++:=default一些说明
我们知道=default是当我们需要合成默认版本的构造函数或者拷贝控制成员的时候使用的。同时,当我们在类内声明的时候使用=default时,函数被隐式声明为内联函数。当我们不想声明为内联函数的话,就在类外的定义处添加=default就好了。...原创 2018-11-16 10:25:34 · 3562 阅读 · 0 评论 -
WSP框架:WEB组件的原理
C++容器的工作流程如下所示:用户在浏览器输入URL地址; 浏览器根据URL地址生成HTTP请求,发给Web服务器,也就是C++容器; C++容器收到HTTP请求后,唤醒业务逻辑线程,由它来处理该请求。业务逻辑线程根据URL和配置文件进行匹配(TAF平台),构造相应的MyCommand对象并调用其doProcess成员函数来处理请求; ...原创 2019-07-01 20:11:43 · 509 阅读 · 0 评论 -
gdb调试
gcc作为GNU开源的C编译工具,自带优化功能。可以针对当前代码进行一定程度的优化,在保证程序正确运行的基础之上,减少系统资源的占用。"-On"选项就是进行代码编译优化的!n是等级项,一般默认的是1,也即是“-O1”(一般直接写作“-O”)。"-On"选项中n的数值越大,优化的等级越高,同时也就意味着程序的运行速度越快。一般常用的等级是-O2.而gdb是gcc的调试工具,主要用于C/C...原创 2019-05-13 17:14:08 · 248 阅读 · 0 评论 -
GCC : 什么是编译?什么是静态库?什么是动态库?怎么生成?优先级?
本文旨在让大家真正明白C程序如何运行、库文件的种类区别、如何生成、如何使用等!一、简介:gcc 最初是 "GNU C Compiler" 的简称,只是当作一个 C 语言的编译器,现在已经变成了 "GNU Compiler Collection",可以编译多种语言。常用的命令参数选项:二、编译的四个阶段:在使用 gcc 编译程序时,编译过程可以被细分为 4 个阶段:...原创 2019-05-11 12:01:53 · 1477 阅读 · 1 评论 -
C++中const用于函数重载
常成员函数和非常成员函数之间的重载首先先回忆一下常成员函数声明:<类型标志符>函数名(参数表)const;说明:(1)const是函数类型的一部分,在实现部分也要带该关键字。(2)const关键字可以用于对重载函数的区分。(3)常成员函数不能更新类的成员变量,也不能调用该类中没有用const修饰的成员函数,只能调用常成员函数。(4)非常量对象也可以调用常成员...原创 2019-05-10 11:39:55 · 240 阅读 · 0 评论 -
VPTR的分步初始化
假设一个含有虚函数的子类。C++类在编译的时候,分配内存,提前布局虚函数表,定义VPTR;当创建对象的时候,初始化子类的VPTR,使其指向父类的虚函数表;当父类的构造函数运行结束的时候,子类的VPTR指向子类本身的虚函数表;因此,当父类的构造函数调用虚函数的时候,调用的是父类自己的虚函数;当子类的构造函数调用虚函数的时候,调用的是子类自己的虚函数...原创 2019-05-19 23:20:37 · 310 阅读 · 0 评论 -
构造函数不可以声明为虚函数,析构函数可以声明为虚函数
构造函数不能声明为虚函数,而析构函数可以声明为虚函数,在有的情景下析构函数必须声明为虚函数。不建议在构造函数和析构函数里调用虚函数。构造函数不能声明为虚函数的原因?构造一个对象时,必须知道对象实际类型,而虚函数是在运行期间确定实际类型的。而在构造一个对象时,由于对象还未构造成功,编译器就无法知道对象的实际类型,是该类本身,还是派生类,还是其他。虚函数的执行依赖于虚函数表,而虚函数表...原创 2019-05-08 17:47:55 · 968 阅读 · 0 评论 -
C++面向对象基础(二)
面向对象基础能够准确理解下面这些问题是从C程序员向C++程序员进阶的基础。当然了,这只是一部分。 面向对象三大特性? 封装性:数据和代码捆绑在一起,避免外界干扰和不确定性访问。 继承性:让某种类型对象获得另一个类型对象的属性和方法。 多态性:同一事物表现出不同事物的能力,即向不同对象发送同一消息,不同的对象在接收时会产生不同的行为(重载实现编译时...原创 2019-05-08 17:44:33 · 290 阅读 · 0 评论 -
C++基础汇总(一)
C/C++的内容又多又杂,常常看到有人罗列相关书单,觉得毫无意义,我不相信他们真的完全掌握了其中任何一本。学习任何东西,首先要掌握基本概念,基础不牢地动山摇,因为高级的内容都是通过低级的概念来描述的。当基本概念都没理解透,学习再多都是空中楼阁。这里罗列了一些听基本的问题,虽然看着不难,但是精确理解每句话中的每个词真的并不容易。 变量声明和定义区别? 声明仅仅是把变量的声明的位置及类...原创 2019-05-08 16:12:24 · 236 阅读 · 0 评论 -
C++:左值和右值
C++ 中的左值(Lvalues)和右值(Rvalues)C++ 中有两种类型的表达式:左值(lvalue):指向内存位置的表达式被称为左值(lvalue)表达式。左值可以出现在赋值号的左边或右边。 右值(rvalue):术语右值(rvalue)指的是存储在内存中某些地址的数值。右值是不能对其进行赋值的表达式,也就是说,右值可以出现在赋值号的右边,但不能出现在赋值号的左边。变量是左值,...原创 2019-04-23 09:20:30 · 1226 阅读 · 0 评论 -
C++:引用
引用的意义: 1)引用作为其他变量的别名而存在,因此在一些场合可以代替指针 2)引用相对于指针来说具有更好的可读性和实用性引用的性质: 1、单独定义普通引用时 必须初始化,说明很像一个常量 2、普通引用也占内存空间引用的本质1)引用在C++中的内部实现是一个指针int name = int *const name...原创 2019-04-23 09:06:25 · 151 阅读 · 0 评论 -
C++:const分配内存情况分析
//1、局部变量const int a = 10 ;int * p = &a //分配临时内存指针不可修改const int a = 10 ; 这句话表示const int a是存放在符号表中的常量,a是键,10是值。平时是不分配空间的。int * p = &a,这句话的时候,系统会临时在栈区分配一个临时空间temp,temp空间的值是10.之后将临时空间的...原创 2019-04-22 19:48:49 · 752 阅读 · 0 评论 -
C/C++常见的预处理指令
本文主要记录了C/C++预处理指令,常见的预处理指令如下:#空指令,无任何效果 #include包含一个源代码文件 #define定义宏 #undef取消已定义的宏 #if如果给定条件为真,则编译下面代码 #ifdef如果宏已经定义,则编译下面代码 #ifndef如果宏没有定义,则编译下面代码 #elif如果前面的#if给定条件不为真,当前条件为真,则编译下面代码 #endif...原创 2019-01-05 10:30:44 · 252 阅读 · 0 评论 -
43.StrVec类:std::move调用移动构造函数的一个实例
自定义一个strvec类,在内存不够,开辟新的内存存放元素的时候(也即是reallocate),使用移动操作!而非拷贝!using namespace std;class strvec{private: static allocator<string>alloc; void chk_n_alloc() { if (size() == capacity()) reall...原创 2018-10-18 21:17:48 · 379 阅读 · 0 评论 -
42.移动构造函数的合成规则
不会使用移动造作:当类的类成员定义了自己的拷贝构造函数且未定义移动构造函数当类的类成员没有定义自己的拷贝构造函数且编译器不能为其合成移动构造函数当有类的成员的移动构造函数或者移动赋值运算符是删除的或者不可访问的当类的成员存在成员引用或者const的时候,移动赋值运算符被定义为删除的如果一个类定义了自己的移动构造函数和/或移动赋值运算符,则该类的拷贝构造函数和拷贝赋值运算符被定义...原创 2018-10-18 21:12:51 · 715 阅读 · 0 评论 -
41.简单说一下noexecpt关键字
在内存资源管理中,有拷贝构造函数和移动构造函数。有的时候,拷贝会比移动更加浪费资源,消耗性能。你比如说,vector,当我们的vector不够空间让我们push_back的时候,它的内部机制会重新开辟一块内存,将原来的元素拷贝进新的大的内存,然后销毁之前的vector内存,这样一来的话就出现了拷贝后又销毁的情况。那样多浪费系统资源啊,拉低性能。所以呢,既然拷贝后还要销毁原来的内存,那我直接...原创 2018-10-18 20:49:33 · 230 阅读 · 0 评论 -
29.默认构造函数
构造函数的任务是 初始化类对象的数据成员,创建对象。无论何时只要类的对象被创建,就会自动执行构造函数!不同于其他的成员函数,构造函数不能被声明为const。当我们为类创建一个const对象的时候,直到构造函数执行完初始化过程,对象才算真正的获得常量属性。因此,构造函数可以在const对象创建的过程中向其写值!默认构造函数又称为合成构造函数!对于大多数的类来说,执行合成构造函数按照如下规...原创 2018-10-11 22:22:10 · 266 阅读 · 0 评论 -
28.构造函数中,成员变量一定要通过初始化列表来初始化的?
首先要明确:如果对象成员是const或者引用的话,必须将其初始化!构造函数中,成员变量一定要通过初始化列表来初始化的的几种情况!1)对象成员是const或者引用#include <iostream>using namespace std;class A{public: A(int &v) : i(v), p(v), j(v) {} voi...原创 2018-10-11 22:08:04 · 573 阅读 · 0 评论 -
27.能否在构造函数中抛出异常?析构函数呢?
首先,我们要明确一点!一个函数执行的过程中,如果抛出异常,会导致函数提前终止!在C++构造函数中,既需要分配内存,又需要抛出异常时要特别注意防止内存泄露的情况发生。因为在构造函数中抛出异常,在概念上将被视为该对象没有被成功构造,因此当前对象的析构函数就不会被调用。同时,由于构造函数本身也是一个函数,在函数体内抛出异常将导致当前函数运行结束,并释放已经构造的成员对象,包括其基类的成员,即执行直接...原创 2018-10-11 21:50:58 · 587 阅读 · 0 评论 -
26.智能指针和动态内存
在C++中,动态内存的管理是通过一对运算符来完成的。new在动态内存中为对象分配空间并返回一个指向该内存对象的指针。delete,接受一个动态对象的指针,销毁该对象,并释放与之关联的内存!为什么要用智能指针?动态内存的使用很容易出现问题,因为确保在正确的时间释放内存是极其困难的。有时候我们会忘记释放内存这就会导致产生内存泄漏;为了更容易同时也更安全的使用动态内存,新的标准库提供了两种智...原创 2018-10-11 21:07:30 · 212 阅读 · 0 评论 -
25.C++:最通俗的讲解,什么是面向过程?什么是面向对象?
网上关于这两个的回答真的很多,但是都有一个共同特点:------------不容易懂。我今天就简单通俗的说一下(当然,如果你要非常深入的了解,这篇不适合你。如果你只是为了了解什么是面向过程和面向对象,怎么面对考试,面对面试,怎么和别人说两者区别,看我下面几段话够了。)先来两小段通俗解释面向过程(Procedure Oriented 简称PO :像C语言): 看名字它是注重过程的。当解决...原创 2018-10-11 19:29:54 · 790 阅读 · 0 评论 -
9.C++弱引用智能指针weak_ptr的用处
weak_ptr也是一个引用计数型智能指针,但是它不增加对象的引用计数,即弱引用。与之相对,shared_ptr是强引用,只要有一个指向对象的shared_ptr存在,该对象就不会析构,直到指向对象的最后一个shared_ptr析构或reset()时才会被销毁。利用weak_ptr,我们可以解决常见的空悬指针问题以及循环引用问题。主要是利用了weak_ptr的lock()实现指针的提升!...原创 2018-09-20 15:16:36 · 368 阅读 · 0 评论 -
0.C++之RAII技术解析
1.什么是RAII 技术?我们在C++中经常使用new申请了内存空间,但是却也经常忘记delete回收申请的空间,容易造成内存泄露,于是RAII技术就诞生了,来解决这样的问题。RAII(Resource Acquisition Is Initialization)机制是Bjarne Stroustrup首先提出的,是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等...原创 2018-06-27 19:42:05 · 276 阅读 · 0 评论