C/C++
文章平均质量分 63
爱很遥远
事有其道
展开
-
《Effective C++ 改善程序与设计的55个具体做法》——第五章笔记
实现条款26:尽可能延后变量定义式的出现时间只要定义了一个变量且该变量类型有构造和析构函数,那么当程序运行到定义式时就会有构造成本,离开作用域时就会有析构成本。即使这个变量并未被使用。尽可能延后的真正意义:你不只应该延后定义直到非得使用该变量的前一刻为止,甚至应该尝试延后定义直到能够给他初值实参为止。这样不仅能够避免构造和析构非必要对象,还可以避免无意义的默认构造行为。(因为这时不用先原创 2015-03-22 19:19:29 · 433 阅读 · 0 评论 -
C++11新特性——容器相关(三)tuple
tuple是类似pair的模板。每个pair的成员类型都不相同,但每个pair都恰好有两个成员。不同tuple类型的成员类型也不相同,但一个tuple可以有任意数量的成员。每个确定的tuple类型的成员数目是固定的,但一个tuple类型的成员数目可以与另一个tuple类型不同。 当我们希望将一些数据组合成单一对象,但又不想麻烦地定义一个新数据结构来表示些数据时,tuple是非常有原创 2016-12-02 09:13:13 · 487 阅读 · 0 评论 -
C语言中变长参数的函数的实现
当我们定义一个函数时,有可能无法确定参数的个数,这是就需要用到变长参数函数,就想标准C函数printf一样。一般这样声明:void func(char* form, ...);前面至少有一个确定的参数。函数体内如何获取这些参数呢?这就需要用到几个宏以及了解他们的原理。函数参数是以数据结构——栈的形式存取,从右至左入栈。因此,从理论上说,我们只要探测到任意一个变量的地址,并且知道其他变量原创 2016-04-24 17:26:06 · 7941 阅读 · 1 评论 -
C++11之lambda表达式——C++ Primer
lambda表达式表示一个可调用的代码单元。我们可以将其理解为一个未命名的内联函数。与其他函数类似,lambda具有返回类型、参数列表和函数体。但与函数不同,lambda可能定义在函数内部。lambda表达式具有如下形式:[capture list] (parameter lisi) -> return type { function body }其中,capture list(捕获列表)原创 2016-11-27 11:18:33 · 962 阅读 · 0 评论 -
线程函数和类成员函数
创建线程时,需要指定线程的入口函数。一般来讲,线程函数为全局函数或静态函数。类的成员函数默认含有this指针作为参数,与线程函数指针类型不匹配,不能将类的成员函数指定为线程函数。如何在线程中执行类的成员函数或者访问数据成员呢? 最常用的方法就是线程函数还是用全局或静态函数,然后把类对象指针或this作为线程函数参数传入,在线程函数中将void类型参数强转为对应类型,再去操作。原创 2016-12-22 15:50:29 · 684 阅读 · 0 评论 -
实现一个getMin功能的栈
题目:实现一个特殊的栈,在实现栈基本功能的基础上,再实现返回栈中最小元素的操作。要求pop、push、getMin时间复杂度都是O(1),设计时使用现成的栈结构。 用C++实现了一下。template class MyStack{public: void Push(const T& t) { m_data.push(t); if原创 2017-02-12 21:47:44 · 492 阅读 · 0 评论 -
用两个栈实现一个队列的基本功能
题目:用两个栈实现队列的基本功能。 实现:一个栈用于接受输入,一个用于输出,仅当输出栈空时,将输入栈中的数据一次性压入输出栈。以下实现中,该动作在pop和front中进行。 C++实现如下:template class MyQueue{public: void Push(const T& t) { m_in.push(t); }原创 2017-02-12 23:00:05 · 398 阅读 · 0 评论 -
char*做map的key使用时的问题
今天在工作中使用到map时,map中用char*字符串做key,后面通过key做find操作,发现找不到之前插入的元素。通过网上搜索,得出结论,find时,默认使用== 进行判断,char*只是指针,如果两个字符串值相同,但是地址不同,是无法匹配的。 所以最好使用std::string。如果非要用char*,需要使用find_if函数并且用bind2sd函数指定比较函数。#i原创 2017-03-08 22:14:35 · 2678 阅读 · 0 评论 -
memmove和memcpy函数
两个函数都在头文件string.h中定义,函数原型为: void * __cdecl memcpy(void *dst, const void *src, size_t count); void * __cdecl memmove(void *dst, const void *src, size_t count);实现代码如下:void * __转载 2017-03-31 10:56:40 · 311 阅读 · 0 评论 -
linux环境下的内存泄漏检查
Linux下的mtrace工具可以帮助我们检查程序中是否有内存泄漏。GNU扩展函数mtrace会为内存分配函数(malloc, realloc, memalign, free等)注册hook,记录malloc/free信息。 使用时也非常简单,只需在代码中调用mtrace函数即可。这需要包含头文件mcheck.h。同时需要设置环境变量MALLOC_TRACE,指定信息输出到哪个文原创 2017-03-02 21:54:36 · 558 阅读 · 0 评论 -
C++11 bind函数
bind标准库函数,定义在头文件functional中。可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。 调用bind的一般形式为: auto newCallable = bind(callable,arg_list); 其中,newCallable是一个可调用对象,arg_l原创 2017-04-13 13:55:14 · 405 阅读 · 0 评论 -
C++11中的std::call_once
某些场景下,我们需要代码只被执行一次,比如单例类的初始化,考虑到多线程安全,需要进行加锁控制。C++11中提供的call_once可以很好的满足这种需求,使用又非常简单。头文件#include template void call_once (once_flag& flag, Fn&& fn, Args&&...args); 第一个参数是原创 2017-04-30 16:50:00 · 24644 阅读 · 1 评论 -
C++11多线程
一点笔记,后续展开。thread给线程函数传参默认是值传递,如果需要引用传递,使用std::ref对参数取引用。或是使用std::move取右值引用,前提是参数传递后不会在原线程使用。 std::thread::hardware_concurrency()获取CPU个数,对设置线程数有很大的参考意义。 std::lock使用死锁避免算法来Lock给定的Locka原创 2017-05-01 10:26:06 · 333 阅读 · 0 评论 -
C++ Primer 右值引用和move语义
C++11中提供了移动对象而非拷贝对象的功能。有时候,对象拷贝后就立即销毁了,这时移动对象会大幅提升性能。很多情况下拷贝对象是不必要的,还有IO类及unique_ptr类这些不可拷贝的类对象,但可以移动。旧C++标准中,没有移动对象的方法,即使没必要拷贝也不得不拷贝。容器中所保存的类必须是可拷贝的。新标准中,容器可以保存不可拷贝的类,只要能被移动即可。标准库容器、string、shared_p原创 2017-04-19 22:15:57 · 493 阅读 · 0 评论 -
用C++11的std::async代替线程的创建
http://www.cnblogs.com/qicosmos/p/3534211.htmlc++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的:void f(int n);std::thread t(f, 5);t.join();但是线程毕竟是属于比较低层次的东西,有时候使用有些不便,比如我希望获取线程函数的返回结果的时候,我就不能直接通过t转载 2017-05-02 11:08:24 · 238 阅读 · 0 评论 -
自己编写的简单的线程池
利用C++11的std::thread,实现生产消费模型。/*任务接口*/#ifndef _ITASK_HEAD_#define _ITASK_HEAD_class ITask{public: ITask(void *arg = nullptr) :m_arg(arg) { } virtual ~ITask() { } void原创 2017-04-23 19:58:25 · 346 阅读 · 0 评论 -
char data[0]问题
问题:当进行内存管理时,经常需要一个额外的结构,例如struct MyData{ char*data; // 指向分配的内存空间 intlen; // 记录空间大小};这样,需要进行四步操作,先分配MyData结构体,再分配要管理的内存,再让data指针指向该内存空间,再把空间大小赋给len。问题,该结构在64位系统上sizeof结果是多少?可以修改结构体的原创 2017-06-07 09:05:15 · 1496 阅读 · 0 评论 -
C++11新特性之容器相关(一)
容器的容器 在早期版本的C++标准中如果vector的元素还是vector(或者其他模板类型),定义的形式与C++11新标准略有不同。过去,必须在外层vector对象的右尖括号和其元素类型之间添加一个空格,写成vector >而非vector>。 cbegin和cend 原来的begin和end返回的iterator是否是常量取决于对应的容器类型,但原创 2016-11-30 09:20:00 · 502 阅读 · 0 评论 -
C++11新特性——容器相关(二)swap
swap 新标准中提供了非成员版本的swap操作,此操作对array容器,会交换元素的值;对其他容器,则只交换容器的内部结构,并不进行元素值的拷贝操作,所以在这种情况下是非常迅速的。正因如此,当swap array后,原来array上的迭代器还依然指向原有元素,只是元素的值变了;而swap非array容器之后,原来容器上的迭代器将指向对方容器上的元素,而指向的元素的值却保持不原创 2016-12-01 08:46:44 · 2654 阅读 · 0 评论 -
函数指针
本文不涉及函数的底层实现原理,只是讲述一下一般函数指针和类成员函数指针的声明和使用。一般函数指针相对简单,例如: int max(int x, int y) { return x > y ? x : y; } int (*pfunc)(int, int); pfunc=原创 2016-11-15 08:59:14 · 209 阅读 · 0 评论 -
《Effective C++ 改善程序与设计的55个具体做法》——第四章笔记
设计与声明条款18:让接口容易被正确使用,不易被误用理想上,如果客户企图使用某个接口而却没有获得他所预期的行为,这个代码不应该通过编译;如果代码通过了编译,它的作为就应该是客户所想要的。导入新类型可以预防许多客户端错误。正确类型设定后,限制其值有时候就合情合理。预防客户端错误的另一个方法是限制类型内什么事可做,什么不可做。常见的如加const。尽量令你的type的行为与内置类型原创 2015-03-21 21:06:54 · 583 阅读 · 0 评论 -
《Effective C++ 改善程序与设计的55个具体做法》——第三章笔记
资源管理读这章的时候发现之前对auto_ptr的理解有误,所以找了一些书重新看了一下智能指针模板相关的知识,先把这些基本知识附上。auto_ptr是C++98中提出的,C++11中将其摒弃,同时提出了unique_ptr和shared_ptr。三者都定义了类似指针的对象,可以将new获得的地址赋值给对象,智能指针过期后,析构函数将使用delete释放内存,无需手动释放。要创建智能指针,原创 2015-03-19 20:02:33 · 382 阅读 · 0 评论 -
《Effective C++ 改善程序与设计的55个具体做法》——第二章笔记
构造/析构/赋值运算条款5:了解C++默默编写并调用了哪些函数如果自己没有声明,编译器会为类声明一个默认构造函数、拷贝构造函数、赋值操作函数、析构函数。这些函数都是public且inline的。只有这些函数被调用时,才会被编译器创建出来。默认构造函数和析构函数是用来调用基类和非静态成员的构造函数和析构函数。析构函数是非virtual的,除非该类的基类自身声明了virtual析构原创 2015-03-17 20:04:44 · 447 阅读 · 0 评论 -
《Effective C++ 改善程序与设计的55个具体做法》——第一章笔记
导读中有两点注意:构造函数声明为explicit,可以阻止隐式类型转换,禁止编译器执行非预期的类型转换。推荐这样使用,除非有理由进行隐式类型转换。拷贝构造函数:以同型对象初始化自我对象;拷贝赋值操作符:从同型对象拷贝值到自我对象。Widget w2(w1); // 拷贝构造函数w2 = w1; // 拷贝赋值操作符Widget w3 = w2; // 拷贝构造函数区分:如果原创 2015-03-15 20:51:49 · 502 阅读 · 0 评论 -
《More Effective C++ 35个改善编程与设计的有效方法》——第一章笔记
基础议题条款1:仔细区别指针和引用没有空引用,一个引用必须总代表某个对象。如果出现不指向任何对象的情况,应该使用指针;如果总是代表一个对象,不允许出现null,应该使用引用。引用必须有初值,而指针没有此限制。没有空引用,所以不需要测试有效性,但指针在使用前需要测试是否为null。指针可以被重新赋值,指向另一个对象。引用则总指向初始化时的那个对象。一般而言,有不指向任原创 2015-03-29 17:37:20 · 641 阅读 · 0 评论 -
《Effective C++ 改善程序与设计的55个具体做法》——第六章笔记
继承与面向对象设计OOP需要考虑的问题:单一继承还是多重继承?public、protected、private继承?virtual、非virtual继承?缺省参数值与virtual函数有什么交互影响?继承如何影响C++的名称查找规则?设计选项有哪些?Class行为需要修改时virtual函数是最佳选择吗?public继承意味着"is-a",不要带原创 2015-03-28 18:08:53 · 311 阅读 · 0 评论 -
《More Effective C++ 35个改善编程与设计的有效方法》——第二章笔记
重载操作符可能会造成难以理解的错误,需要注意条款5:对定制的类型转换函数保持警觉C++允许编译器在不同类型间执行隐式转换,对自定义类型的转换可以进行控制。两种函数会允许编译器执行这样的转换:单自变量构造函数和隐式类型转换操作符。单自变量构造函数指能够以单一自变量成功调用的构造函数,可能拥有单一参数,也可能有多个参数且除第一个参数外都有默认值。隐式类型转换操作符:关键词o原创 2015-04-26 21:50:36 · 483 阅读 · 0 评论 -
浮点型在内存中的存放方式问题
最近在工作中遇到一个问题:两个子系统按照接口协议通信时,有一个消息字段为double型,但是发送方把一个int64_t的整数memcpy到对应的发送buffer中,接收端按照协议规定对对应的字段按double解析,结果与发送端赋值不同。后来看了一下基本类型在内存中的存储方式才明白其中的原因。float和double型浮点数存储时是有特定格式的,一般采用e指数方式存放。float占4个字节,最高原创 2015-12-22 21:17:17 · 628 阅读 · 0 评论 -
一个C语言函数声明和定义的编译问题
最近在看Redis代码,看到SDS字符串时,有个地方很诡异,代码如下:static inline size_t sdslen(const sds s) { struct sdshdr *sh = (void*)(s-(sizeof(struct sdshdr))); return sh->len;}static inline size_t sdsavail(const s原创 2016-04-24 16:53:13 · 2896 阅读 · 0 评论 -
STL面试问题归总
面试中遇到几个跟STL相关的问题,自己在平时工作中用的不多,很多基础都比较欠缺。回来后查了一下,记录以供后续学习。 问题1、vector的clear函数会释放内存空间吗?如何主动释放被占用的内存空间?当vector、string大量插入数据后,即使删除了大量数据(或者全部都删除,即clear)并没有改变容器的容量(capacity),所以仍然会占用着内存,只析构元素。《Effect原创 2016-11-08 17:18:43 · 866 阅读 · 0 评论 -
面向对象相关面试题归总
面试中遇到几个面向对象相关的基础问题,记录以供后续学习。 问题1、设计一个不能被继承的类。一个类不能被继承,也就是说它的子类不能构造父类,这样子类就没有办法实例化整个子类从而实现子类无法继承父类。我们可以将一个类的构造函数声明为私有,使得这个类的构造函数对子类不可见,那么这个类也就不能继承了。但是,这引出一个问题,客户程序岂不是也无法实例化这个类了?参考一下Singleton模式,用一原创 2016-11-09 18:20:20 · 423 阅读 · 0 评论 -
智能指针
在C/C++编程中,指针的使用非常重要。但是在使用指针时有一个问题就是容易忘记释放相关资源,尤其是堆内存,造成内存泄漏。基于这个原因,出现了智能指针。智能指针其实是一个栈对象,当离开其生命周期时,其析构函数会被调用,我们在析构函数中将资源释放,这样就实现了自动回收的效果。这里主要介绍三种auto_ptr(C++11已摒弃)、unique_ptr、shared_ptr。对于所有智能指针来说,使用原创 2016-11-12 12:23:39 · 377 阅读 · 0 评论 -
C++11新特性——auto和decltype类型推导
C++11新标准引入auto类型说明符,可以让编译器帮我们分析表达式所属的类型,通过初始值推算变量的类型。auto定义的变量必须有初始值。使用auto也能在一条语句中声明多个变量。因为一条声明语句只能有一个数据类型,所以该语句中所有变量的基础数据类型必须相同。 编译器推断出来的auto类型有时候和初始值的类型并不完全一样,编译器会适当的改变结果类型时期更符合初始化规则。比如,使用原创 2016-11-28 22:01:20 · 531 阅读 · 0 评论 -
指针和引用
指针保存一个对象的地址,通过该地址访问对象;引用是对象的别名。二者在概念及使用上需要分清楚。 引用不可以为空,指针可以为空。定义一个引用的时候,必须初始化;声明指针是可以不指向任何对象,即空指针。因此如果一个变量是用于指向另一个对象,它可能为空,这时你应该使用指针;如果变量总是指向一个对象,且不允许变量为空,这时你应该使用引用。由于指针可能为空,使用指针之前必须做判空操作,而引用就原创 2016-11-12 22:33:25 · 397 阅读 · 0 评论 -
malloc与new分配内存
malloc()函数(memory allocation)分配指定长度的内存块。如果分配成功则返回指向被分配内存的指针,分配失败返回NULL。当内存不再使用时,应使用free()函数将内存块释放,防止内存泄漏。返回类型是void*类型。void*表示未确定类型的指针,即申请内存空间时还不知道存储什么类型的数据。C,C++规定,void*类型可以强制转换为任何其它类型的指针。申请了内存空间后原创 2016-11-13 18:01:14 · 1900 阅读 · 0 评论 -
C语言中分配内存的函数
malloc:函数原型:extern void *malloc(unsigned int num_bytes);功能:分配长度为num_bytes字节的内存块返回值:如果分配成功则返回指向被分配内存的指针(此存储区中的初始值不确定),否则返回空指针NULL。void* 表示未确定类型的指针,更明确的说是指申请内存空间时还不知道用户是用这段空间来存储什么类型的数据。C,C++规定,v原创 2016-11-13 18:29:30 · 779 阅读 · 0 评论 -
std::sort排序算法
std::sort的声明语法:template void sort ( RandomAccessIterator first,RandomAccessIterator last );template void sort ( RandomAccessIterator first,RandomAccessIterator last, StrictWeakOrdering comp );原创 2017-06-07 18:13:25 · 16269 阅读 · 1 评论