自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+

Stay hungry, Stay foolish

书山有路勤为径,学海无涯苦作舟

  • 博客(108)
  • 资源 (1)
  • 收藏
  • 关注

原创 等待事件或条件(std::condition_variable)

std::condition_variable的使用

2022-10-16 18:24:31 265

原创 保护共享数据的方式

互斥量是一种通用的机制,但其并非保护共享数据的唯一方式。有很多方式可以在特定情况下,对共享数据提供合适的保护。一个特别极端的情况就是,共享数据在并发访问和初始化时(都需要保护),需要进行隐式同步。这可能是因为数据作为只读方式创建,所以没有同步问题,或者因为必要的保护作为对数据操作的一部分。任何情况下,数据初始化后锁住一个互斥量,纯粹是为了保护其初始化过程,并且会给性能带来不必要的影响。出于以上的原因,C++标准提供了一种纯粹保护共享数据初始化过程的机制。

2022-10-15 18:23:21 332

原创 C++线程之使用互斥量

保护共享数据结构的最基本的方式,就是使用C++标准库提供的互斥量。访问共享数据前,将数据锁住,在访问结束后,再将数据解锁。线程库需要保证,当线程使用互斥量锁住共享数据时,其他的线程都必须等到之前那个线程对数据进行解锁后,才能进行访问数据。互斥量是C++保护数据最通用的机制,但也需要编排代码来保护数据的正确性,并避免接口间的条件竞争也非常重要。不过,互斥量也会造成死锁,或对数据保护的太多(或太少)。

2022-10-13 09:29:47 94

原创 线程的基本操作(五)

第一种,可以通过调用std::thread对象的成员函数get_id()来直接获取,如果std::thread对象没有与任何执行线程相关联,get_id()将返回std::thread::type默认构造值,这个值表示“无线程”。按默认排序比较不同的std::thread::id,当a

2022-09-30 00:45:33 244

原创 线程的基本操作(四)

因为上下文频繁切换会降低线程的性能,所以计算量的最大值和硬件支持线程数,较小的值为启动线程的数量③,std::thread::hardware_concurrency()返回0时,可以选择一个合适的数字,在本例中,选择了2.结束这个例子之前,需要明确:T类型的加法不满足结合律(比如,对于float型或double型,在进行加法操作时,系统很可能会做截断操作),因为对范围中元素的分组,会导致parallel_accumulate得到的结果可能与。启动所有线程后,⑨中的线程会处理最终块的结果。

2022-09-30 00:00:57 245

原创 线程的基本操作(三)

需要在线程对象析构前,显式的等待线程完成,或者分离它,进行赋值时也需要满足这些条件(说明:不能通过赋新值给std::thread对象的方式来"丢弃"一个线程)不过,t1已经有了一个关联的线程执行some_other_function的线程,所以这里系统直接调用。假设通过新线程返回的所有权去调用一个需要后台启动线程的函数,并需要在函数中转移线程的所有权。移动操作⑤完成后,t1与执行some_other_function的线程相关联,t2与任何线程都无关联,t3与执行some_function的线程相关联。

2022-09-21 01:25:42 66

原创 线程的基本操作(二)

移动”是指原始对象中的数据所有权转移给另一对象,从而这些数据就不再在原始对象中保存,std::unique_ptr就是这样一种类型,这种类型为动态分配的对象提供内存自动管理机制。同一时间内,只允许一个std::unique_ptr实例指向一个对象,并且当这个实例销毁时,指向的对象也将被删除。向可调用对象或函数传递参数很简单,只需要将这些参数作为std::thread构造函数的附加参数即可,需要注意的是,这些参数会拷贝至新线程的内存空间中(同临时变量一样),即使函数中的参数是引用的形式,拷贝操作也会执行。

2022-09-18 20:28:26 298

原创 线程的基本操作

线程启动之后要等待线程结束,还是让其自主运行,当std::thread对象销毁之前还没有做出决定,程序就会终止(std::thread的析构函数会调用std::terminate()),因此,即便是有异常存在,也需要确保线程能够正确汇入(joined)或分离(detached)。如果线程分离,就不可能有std::thread对象能引用它,分离线程的确在后台运行,所以分离的线程不能汇入,不过C++运行库保证,当线程退出时,相关资源能够正确回收。如果不等待线程汇入,就必须保证程序结束之前,访问数据的有效性。

2022-09-17 23:48:09 103

原创 程序编译过程

程序编译过程

2022-09-01 00:21:52 26

原创 设计模式定义

解释设计模式模式定义

2022-08-14 19:01:40 99

原创 设计模式——六大设计原则

1.单一职责原则单一职责原则(Single Responsibility Principle)简称SRP,单一职责原则要求一个接口或类只有一个原因引起变化,也就是一个接口或类只有一个职责,它就负责一件事情。单一职责原则的好处:类的复杂性降低,实现什么职责都有清晰明确的定义 可读性提高,复杂性降低 可维护性提高 变更引起的风险降低单一职责适用于接口、类,同时也适用于方法,什么意思呢?一个方法尽可能做一件事情,比如一个方法修改用户密码,不要把这个方法放到“修改用户信息”方法中。对于单一职

2022-05-29 18:16:07 55

原创 类设计者的核查表

1.你的类需要一个构造函数吗?有的类太简单,它们的结构就是它们的接口,所以不需要构造函数。但是,我们现在主要关心的是哪些足够复杂的类,它们需要构造函数来隐藏它们内部工作方式。2.你的数据成员是私有的吗?通常使用公有的数据成员不是什么好事,因为类设计者无法控制何时访问这些成员。3.你的类需要一个无参的构造函数吗?如果一个类已经有了构造函数,而你想声明该类的对象可以不必显示地初始化它们,则必须显示地写一个无参的构造函数。4.是不是每个构造函数初始化所有的数据成员?构造函数的用途就是用

2022-05-09 23:22:19 142

原创 UNIX思想③——组合原则

是什么开发软件时要保证该软件能与其他软件组合使用。换句话说,就是将软件做成一个尽量简单的过滤器。这里所说的过滤器是指接收某种数据流之后,经过加工输出另一种数据流的软件。输出的数据流最好是文本格式。为什么过滤器形式的软件能轻易地连接在一起。软件通过不同的组合方式,能够完成多样的任务。另外。文本流的接口相对简单,这使得软件能够处于信息隐藏的状态。而无法与其他软件协作的软件通常发挥不出多少价值。即便可以使用特殊的进程间通信方式进行协作,软件也会相互暴露内部结构。能作为零件使用的软件要具有独

2022-05-05 23:17:48 160

原创 GIT报错OpenSSL SSL_read: SSL_ERROR_SYSCALL

git clone命令时报错: fatal: unable to access 'https://github.com/XXX.git/': OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 10054 使用以下命令:git config --global http.postBuffer 524288000之后又报错: fatal: unable to access 'https://github.com/XXX.g

2022-05-04 17:10:22 2125 1

原创 编译器链接过程中的强符号和弱符号

属性声明GNU C通过__attribute__声明weak属性,可以将一个强符号转换为弱符号。使用方法如下:__attribute__((weak)) void func(void);__attribute__((weak)) int num;编译器在编译源程序时,无论你是变量名,函数名,在它眼里,都是一个符号而已,用来表征一个地址。编译器会将这些符号集中,存放到一个叫符号表的section中。一个软件工程项目中,可能有多个源文件。如果A.c源文件中定义了一个全局变量num,而B.

2022-04-17 20:30:42 1068

原创 程序目标文件探究

目标文件的格式 编译器编译源代码后生成的文件叫做目标文件。目标文件从结构上讲,它是已经编译后的可执行文件格式,只是还没有经过链接的过程,其中可能有些符号或有些地址还没有被调整。 现在PC平台流行的可执行文件格式主要是windows下的PE(portable executable)和 Linux的ELF(Executable linkable format),它们都是COFF(Common file format)格式的变种。目标文件就是源代码编译后但未进行链接的那些中间文件(...

2022-03-28 23:24:51 584

原创 编译和链接

1.编译和链接合并到一起的过程称为构建。例如“gcc hello.c”命令就包含了非常复杂的过程。2.生成程序被隐藏了的过程——预处理、编译、汇编、链接。预处理(预编译):首先将源代码文件(.c)和相关的头文件(.h)等被预编译期cpp编译成一个.i文件。对于C++程序来说,它的源代码文件的扩展名可能是.cpp,头文件是.hpp,而预编译后的文件扩展名是.ii。第一步预编译的过程相当于如下命令:gcc -E hello.c -o hello.i预编译过程主要处理那些源代码文件中的"#

2022-03-27 20:58:59 1407

原创 More Effective C++ 条款13:以引用方式捕获异常

写一个catch子句时,你必须指明异常对象如何被传递到这个子句来。可以选择通过指针、值、引用方式。指针效率最高,因为抛出指针是唯一在搬移“异常相关信息”时不需要复制对象的一种做法。void someFunction(){ static exception ex; ... throw &ex; ...}void doSomething(){ try{ someFunction(); } catch(except

2022-03-20 16:21:12 637

原创 More Effective C++ 条款12:了解“抛出一个异常”与“传递一个参数”或“调用一个虚函数”之间的差异

相同点:函数参数和异常的传递方式有3种:传值、传引用、传指针。不同点,试看以下函数,不但传递一个widget作为参数,也抛出一个Widget exception://此函数从一个stream中读取一个Widgetistream operator>>(istream& s, Widget& w);void passAndThrowWidget(){ Widget localWidget; cin >> localWidget; //将

2022-03-20 02:44:46 40

原创 More Effective C++ 条款11:禁止异常流出析构之外

两种情况下析构会被调用。第一种是当对象在状态下被销毁,也就是离开它的生存空间或是被明确删除;第二种情况是当对象被异常处理机制——也就是异常传播过程中的stack-unwinding(栈展开)机制——销毁。在运行时期间从函数调用栈中删除函数实体,称为栈展开。栈展开通常用于异常处理。在C++中,如果一个异常发生了,会线性的搜索函数调用栈,来寻找异常处理者,并且带有异常处理的函数之前的所有实体,都会从函数调用栈中删除。所以,如果异常没有在抛出它的函数中被处理,则会激活栈展开。参考下面程序:#in

2022-03-18 00:39:09 39

原创 More Effective C++ 条款10:在构造内阻止资源泄漏

当在构造函数中抛出异常的时候,由于对象尚未构造完全,因此并不会调用其析构函数,问题是此时如果对象已经被部分构造,那么我们应当保证被部分构造的内容适当地析构。考虑这样一个类class A{public: A(const int& number,const string&a,const string& b):num(number),ptr_a(0),ptr_b(0){ if (a != "") ptr_a = new strin

2022-03-16 21:31:56 941

原创 More Effective C++ 条款09:利用析构函数避免资源泄漏

class ALA{public: virtual void processAdoption() = 0;};class Puppy : public ALA{public: virtual void processAdoption();};class Kitten: public ALA{public: virtual void processAdoption();};//核心函数void processAdoptions(istream&.

2022-03-14 23:36:42 755

原创 More Effective C++ 条款08:了解各种不同意义的new和delete

当你写string *ps = new string(“Hands up!”)时,你所使用的new是所谓的new operator,它其实干了两件事:一、分配足够的内存(实际大小是大于所创建的对象大小)二、调用对象构造函数,为刚才分配的内存对象设定初值。new operator永远干这两件事,无论如何你不能改变其行为。上面的那段代码大约反映以下的行为:void *mem = operator new(sizeof(string));call string::string(“Hands

2022-03-14 00:21:19 196

原创 More Effective C++ 条款07:千万不要重载&&,||和,操作符

C++对于“真假表达式”采用所谓的骤死式评估方式。意思是一单该表达式的真假值确定,即使表达式中还有部分尚未检验,整个评估工作仍高结束。举例:char *p;...if((p != 0) && (strlen(p) > 10))你无需担心调用strlen时p是否为null指针,因为如果"p是否为0"的测试结果是否定的,strlen就绝不会被调用。同样道理,以下代码:int rangeCheck(int index){ if((index < lower

2022-03-12 23:33:37 853

原创 More Effective C++ 条款06:区别自增/自减操作符的前置和后置形式

重载方式:class UPInt{public: UPInt& operator++(); //前置式++ const UPInt operator++(int); //后置式++ UPInt& operator--(); //前置式-- const UPInt operator--(int); //后置式-- UPInt& operator+=(int); //+=操作符,结合UPInts和ints};UPInt i

2022-03-10 23:30:00 898

原创 More Effective C++ 条款05:对定制的类型转换函数保持警觉

C++的类型转换,两种函数允许编译器执行这样的操作:单参数构造和隐式类型转换操作符。单参数构造指可能声明单一参数,有可能拥有多个参数,并且除了第一参数之外都有默认值:class Name{public: Name(const string& s); //可以把string转换为name ...};class Rational{public: Rational(int numerator = 0, int denominator = 1); //可以把

2022-03-09 23:26:13 543

原创 More Effective C++ 条款04:非必要不提供默认构造函数

所谓默认构造函数,就是不给任何变量,就可以给调用(无参或参数为默认值)。基本准则:凡可以“合理地从无到有生成对象”的类,都应该包含默认构造函数,而“必须有某些外来信息才能生成对象”的类,则不必拥有默认构造函数。但如果类缺乏一个默认构造函数,当你使用这个类时便会有某些限制。考虑下面这个针对公司仪器而设计的class,在其中,仪器识别码是一定得有的一个构造参数:class EquipmentPiece{public: EquipmentPiece(int ID); ...

2022-03-09 00:24:40 102

原创 More Effective C++ 条款03:绝对不要以多态方式处理数组

class BST {...};class BalancedBST : public BST{ ...};现在考虑有个函数,用来打印BSTs数组中的每一个BSTs数组中的每一个BST的内容:void printBSTArray(ostream& s, const BST array[], int numElements){ for(int i = 0; i < numElements; ++i){ s << array[i]; .

2022-03-06 22:46:54 362

原创 C++实战笔记(六)

迭代器容器一般会提供成员函数begin()/end()/cbegin()/cend().调用它们就可以得到表示两个端点的迭代器,有"c"前缀的函数返回的是常量迭代器,但具体类型最好用自动类型推导:vector<int> v = {1, 2, 3, 4, 5};anto iter1 = v.begin();auto iter2 = v.end();//全局函数,效果一样auto iter3 = std::begin(v);auto iter3 = std::end(v);

2022-03-06 15:24:27 331

原创 C++实战笔记(五)

标准容器C++容器分类:顺序容器,有序容器,无序容器。所有的容器都有一个基本的特性:容器保存元素采用的是值语义,也就是说,里面存储的是元素的副本、复件,而不是引用。从这个基本的特性可以得出一个推论,容器操作元素的很大一块成本就是值的复制。所以,如果元素比较大, 或者非常多,那么操作时的复制成本就会很高,性能也就不会太好。一种解决办法就是尽量为元素实现转移构造函数和转移赋值函数,在加入容器的时候使用std::move来转移元素,降低元素复制的成本。例如:Point p; //复制成本很高

2022-02-28 22:29:19 549

原创 解决: g++: internal compiler error: Killed (program cc1plus)

查了很多资料,最后发现主要原因是内存不足,g++编译时需要大量内存, 临时使用交换分区来解决吧虚拟机直接调整内存大小,远程服务器可使用以下命令命令行输入:sudo dd if=/dev/zero of=/swapfile bs=64M count=16sudo mkswap /swapfilesudo swapon /swapfile编辑完成后,退还空间:sudo swapoff /swapfilesudo rm /swapfile...

2022-02-27 03:17:19 215

原创 C++实战笔记(四)

智能指针unique_ptrunique_ptr是最简单、最容易使用的智能指针之一,在声明的时候必须用模板参数指定类型,例如:unique_ptr<int> ptr1(new int(10)); //int智能指针assert(*ptr1 = 10); // 使用*获取内容assert(ptr1 != nullptr); //可以判断是否为空指针unique_ptr<string> ptr2(new string("hello")); //string智能指

2022-02-23 23:07:17 382

原创 C++实战笔记(三)

const/volatile关键字const表示常量,较简单的用法就是定义程序的数字、字符串常量、代替宏定义等,例如const int MAX_LEN = 1024;const std::string NAME = "meto";从C++程序生命周期的角度来看,我们就会发现它和宏定义还是本质区别的:const定义的常量在预处理阶段并不存在,直到运行阶段才出现。它叫只读变量更合适。既然它是变量,那么使用指针获取地址,再强制写入也是可以的,但这种做法破坏了常量性,绝对不提倡。下面一个

2022-02-18 00:50:26 350

原创 C++实战笔记(二)

final标识符C++11新增final标识符,把final用于类定义,就可以显示地禁用继承,防止有人有意或者无意创建派生类,这个标识符无论对人还是编译器,效果都很好,建议积极使用。例如:class DemoClass final //禁止任何人继承{...}final也可以用于虚函数,禁止这个虚函数再被子类重载,这样就可以更精细地控制继承类的使用:class Interface //接口类定义,没有final,可以被继承{ virtual void f() = 0;

2022-02-09 22:02:48 527

原创 Andriod Studio-gradle build时间过长解决方案

在创建好的项目文件夹内,找到build.gradle文件,使用notepad打开文件,将repositories代码原内容注释,改为以下部分代码:// Top-level build file where you can add configuration options common to all sub-projects/modules.buildscript { repositories { //google() //mavenCentral() m

2022-01-23 13:46:15 1947

原创 C++实战笔记(一)

命名规范:变量、函数名和命名空间用snake_case,全局变量加"g_"前缀 自定义类名用CamelCase风格,成员函数用snake_case,成员变量加"m_"前缀。 宏和常量应当全大写,单词之间用下划线连接 尽量不要将下划线作为变量的前缀或后缀,很难识别CamelCase:驼峰命名法,分为大驼峰,小驼峰。区别为首字符是否要大小写。snake_case:用的全是小写,单词之间用下划线连接。#define MAX_PATH_LEN 256 //常量全大写int g_sys

2022-01-20 00:59:40 608

原创 C++可调用对象与function

C++语言有几种可调用对象:函数、函数指针、lambda表达式、bind创建的对象以及重载了函数调用运算符的类。和其他对象一样,可调用的对象也有类类型。例如,每个lambda有它自己唯一的(未命名)类类型;函数及函数指针的类型则由其返回值类型和实参类型决定。然而,两种不同类型的可调用对象却可能共享同一种调用形式。调用形式指明了调用返回的类型以及传递给调用的实参类型。一种调用形式对应一个函数类型,例如:int(int, int);是一个函数类型,它接受两个int,返回一个int不同类

2022-01-16 18:44:16 144

原创 C++ 对象移动

右值引用为了支持移动操作,新标准引入了一种新的引用类型——右值引用,所谓右值引用就是必须绑定右值的引用,我们通过&&而不是&来获得右值引用。右值引用有一个重要的性质:只能绑定到一个将要销毁的对象。因此我们可以自由地将一个右值引用的资源“移动”到另一个对象中。一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。...

2022-01-15 22:21:50 509

原创 C++ allocator类

C++ allocator类讲解

2022-01-06 00:31:14 300 1

原创 C++智能指针和动态内存

标准库提供了一个可以管理new分配的数组的unique_ptr版本。为了用一个unique_ptr管理动态数组,我们必须在对象类型后面跟一对空方括号://up指向一个包含10个未初始化int的数组unique_ptr<int[]> up(new int[10]);up.release(); //自动用delete[]销毁其指针类型说明符中的方括号指出up指向一个int数组而不是一个int。当一个unique_ptr指向的是一个数组时,我们不能使用点和箭头成员运算符号。毕竟un

2022-01-03 15:55:11 224

小区物业管理系统的数据库设计和数据操作

通过对某小区的物业管理进行分析、调查,设计该小区的物业管理系统。 系统模块设计: 小区物业管理系统,力求与实际相结合具有小区日常管理和统计等功能,旨在达到使小区的管理和人事数字化使之更加方便快捷以提高工作效率。主要是收费管理模块、物业管理模块、系统管理模块。

2013-12-21

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除