那些年躲过的坑儿
文章平均质量分 52
注意记录开发过程中遇到的问题;警示自我,提醒他人。
一苇渡江694
无有功德,一苇渡江
展开
-
没有躲过的坑--你开发的软件安装在C盘Program Files (x86)下产生的异常
今天偶然发现的问题,就是自己写的win32程序安装在C盘Program Files (x86)文件夹下就会产生异常,而安装在其他文件夹,即使是D盘的Program Files (x86)下,程序也可以完美运行。引起这个,肯定是权限的问题。这个软件运行时,需要读写数据库,以及各种缓存数据。这就是我给自己挖的一个坑儿,相信很多人也会遇到这个问题。就是在开发程序、VS调试的时候,总喜欢使用当前路径,或者是原创 2015-12-03 20:46:58 · 15946 阅读 · 0 评论 -
没有躲过的坑--std::string初始化、最快速判断字符串为空
之前说过,记得给变量初始化。今天突然想到了一个问题,如果声明了一std::string类型,怎么初始化呢?std::string test_string;std::string test_string_empty = "";std::string test_string_null = NULL;//运行错误,而非编译错误简单测试:#include<iostream>int main(){原创 2015-12-03 00:47:57 · 31404 阅读 · 2 评论 -
没有躲过的坑--0xC0000005: 读取位置 xxx时发生访问冲突
Bjarne Stroustrup老爷子说过: “C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.” 最近的工程时不时的出现0xC0000005: 读取位置 xxx时发生访问冲突,导致崩溃。先看看下面的程序:#includ原创 2015-12-01 22:57:45 · 72908 阅读 · 6 评论 -
没有躲过的坑--C++函数的默认参数(重新定义默认参数)
默认参数指的是当函数调用中省略了实参时,自动使用一个值。这里首先需要注意的是: 对于带参数列表的函数,必须从右向左添加默认值。 也就是说,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值。今天遇到的坑儿,就是函数使用默认参数,并且函数的声明和定义是分开的。char* left(const char* str, int n=1);int main(){}char* left(cons原创 2015-12-01 21:06:45 · 10957 阅读 · 0 评论 -
没有躲过的坑--vector使用erase后迭代器变成野指针
vector上镜率非常高,但是最近又被他fuck了一下。使用的就是vector的erase方法。erase–return value 首先需要明确一下vector的两种erase:C++98中是这样的:iterator erase (iterator position);iterator erase (iterator first, iterator last)C++11是这样的:iterat原创 2015-11-30 23:38:11 · 11888 阅读 · 2 评论 -
没有躲过的坑--没有及时break出for循环
break这个词都不陌生,最常用到的就是在switch语句中。如果在switch的case后面忘写了break,就会顺序执行到下一个case的对应的语句。我说的这种情况只是对于C++,对于C Sharp如果忘记了break,编译器是会报错的。仔细想想,好像自己还真没有用过break在其他地方。导致自己又掉入了一个大坑中。比如使用一个for循环查找数组中所要的元素中your_find对应的索引:int原创 2015-11-30 21:19:31 · 3015 阅读 · 1 评论 -
没有躲过的坑--使用太多的全局变量
最近在工程中为了达到目的,使用了很多全局变量,导致程序运行效率降低。在程序运行时,根据需要到内存中相应的存储单元中调用,如果一个变量在程序中频繁使用,例如循环变量,那么,系统就必须多次访问内存中的该单元,影响程序的执行效率。因此,C\C++语言还定义了一种变量,不是保存在内存上,而是直接存储在CPU中的寄存器中,这种变量称为寄存器变量。总觉得有些太low,就Google了一番。首先我们清楚,有个叫寄原创 2015-11-30 20:54:35 · 9722 阅读 · 3 评论 -
没有躲过的坑--new一个指针数组、以及创建动态二维数组
实际工作中,有一个类A,现在需要使用多个A对象的指针,这是时候,首先想到的就是指针数组。———————————————————————————————————————————— 指针数组与数组指针 首先,指针数组和数组指针有何区别是老生常谈的东西: 看中文不方便,看看英文描述:指针数组:array of pointers,即用于存储指针的数组,也就是数组元素都是指针 数组指针:a point原创 2015-11-26 22:19:00 · 17952 阅读 · 4 评论 -
没有躲过的坑--使用using namespace std的坏习惯
使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突。在C++中,变量、函数和类都是大量存在的。如果没有命名空间,这些变量、函数、类的名称将都存在于全局命名空间中,会导致很多冲突。比如,如果我们在自己的程序中定义了一个函数toupper(),这将重写标准库中的toupper()函 数,这是因为这两个函数都是位于全局命名空间中的。命名冲突还会发生在一个程序中使用两个或者更多的第三方库的情况中。原创 2015-11-26 21:20:26 · 19998 阅读 · 3 评论 -
没有躲过的坑--map查找结果处理
通过键-值的方法进行搜索,可以使用map,极大的提高了速度。下面代码就是使用map的find查找,通过键,找出对应的值。map<std::string, int> string_int_map;//对string_int_map进行初始化map<std::string, int >::iterator iter_string_int; string substring_to原创 2015-11-25 22:53:01 · 9020 阅读 · 2 评论 -
没有躲过的坑--有if就要有else(一定成对)
我们都很擅长流程控制,能写出很好很复杂的if语句。但是有时过于兴奋,更多的是过于自信而只写了if,而没有写else。这是一个争论不休的话题,很多人,很多大师都认为有的情况下可以不写else,只写if。支持 if 和 else 成对出现的人认为:不怕一万 就怕万一认为 if 和 else 没必要成对出现的人认为:不便于理解,太多没用的东西。我之前觉得也必须非要这样成对,但是今天在工程中遇到了问题。就是原创 2015-11-25 21:18:58 · 22390 阅读 · 1 评论 -
没有躲过的坑--类中的静态成员变量(static or const static)
工作中是这样的,A类中有一个成员变量x,最开始声明为私有:class A{private: int x;};现在需要在另一个cpp中使用这个x,所以要把它变为共有并且静态:class A{public: static int x;};由此可见: 静态数据成员和普通数据成员一样遵从public,protected,private访问规则。 此时,编译,我们会得到一个错误,原原创 2015-11-24 21:28:06 · 4417 阅读 · 2 评论 -
没有躲过的坑--捕获窗口之外的鼠标消息(钩子还是??)
做一个发送表情的对话框,类似微信和QQ一样的,点击表情按钮,弹出表情框,鼠标点击表情框外时,这个表情框被kill。说白了 就是在这个窗口上获得窗口外面的鼠标消息。Google百度了一番,很多人说道使用钩子,才能获得窗口外面的click事件,这也未免太小题大做了吧。还好发现了一个简简单单的函数: SetCapture(*this); 函数功能:该函数在属于当前线程的指定窗口里设置鼠标捕获。一旦窗口原创 2015-11-23 22:50:02 · 5503 阅读 · 3 评论 -
没有躲过的坑--正则表达式截取字符串
工程中,需要从字符串中匹配出以:开头,并以:结束的字符串。Google还是百度,很多C++的正则表达式都是通过st::tr1或boost库中使用的,但是我们仅仅用一个小小的功能,就用一个库不是很好的办法。对的,之前我的博客已经介绍了C++11的新特性-正则表达式。所以可以不使用其他的库,来完成任务:std::vector<string> all_sub_string = {};std::strin原创 2015-11-23 22:06:36 · 21369 阅读 · 4 评论 -
没有躲过的坑--map的初始化(插入数据)
最近工作中需要使用map,进行查询。首先简单介绍一点map,也许是教科书里讲授最少的STL知识吧。但是在实际工作中map挺重要的,用于查找很方便快捷,尤其是以键和值的形式存在的!1、头文件#include<map>2、map的功能自动建立Key - value的对应。key 和 value可以是任意你需要的类型。 根据key值快速查找记录,查找的复杂度基本是Log(N),如果有1000个记录,最原创 2015-11-23 21:21:00 · 28372 阅读 · 1 评论 -
没有躲过的坑--意想不到的除数为零
工程中有这样一个需求,需要获得一张图片的width和height,然后等比例的显示这张图片。首先是获得得到一张图片的路径,然后计算出他的width和height,然后计算:int resize_width = 160;int resize_height = 160;if (image_width > image_height) { resize_width = 160; resi原创 2015-11-22 22:23:43 · 4884 阅读 · 0 评论 -
没有躲过的坑--成对使用new和delete时要采取相同的形式
new创建类对象与不new区别:new创建类对象需要指针接收,一处初始化,多处使用 new创建类对象使用完需delete销毁 new创建对象直接使用堆空间,而局部不用new定义类对象则使用栈空间 new对象指针用途广泛,比如作为函数返回值、函数参数等而且每个学习C++编程的人都知道成对的使用new和delete,也也就是new申请的内存用delete释放,new []申请的内存由delete原创 2015-11-22 22:02:27 · 2213 阅读 · 1 评论 -
没有躲过的坑--程序中的变量未初始化
变量未初始化是C++编程中最为常见和易犯的错误之一。但是对于全局变量,我们可以不进行初始化,这个变量会默认的用零进行初始化,但是这通常不是一个好的习惯。我们今天先不探讨全局变量还是静态全局变量。那么对于一个全部变量来说,初始化为零和不初始化(编译器替我们初始化为零)又有什么区别吗?全局变量和局部变量初始化与不初始化的区别 即int x 和 int x=0的区别。int x =0; 跟 int x;原创 2015-11-21 14:44:17 · 27615 阅读 · 2 评论 -
没有躲过的坑--重载赋值运算符的自我赋值
C++中有个很重要的事情,就是对于类重载赋值运算符,而达到我们想要的结果。 先看看这几行代码://Window 是一个类Window w;w = w; // 再傻的人也不会这么干w[i] = w[j]; // 这个情况偶尔会发生作为一个优秀的工程师,就要考虑到任何可能的情况。看一段更加完整的代码:class ScrollBar {};class Window{原创 2015-11-21 12:26:51 · 2446 阅读 · 1 评论 -
没有躲过的坑--抽象类不能实例化对象(但是你明明定义的不是抽象类)
今天在开发过程中遇到了一个错误:不能实例化抽象类这个错误完全是自己疏忽大意造成的。首先我们知道,一个类如果是抽象类,我们就不能用这个类实例化一个对象。什么样的类是抽象类呢? C++没有C Sharp中的关键字abstract,但是当一个类中有一个或多个纯虚函数的时候,这个类就自动成为了抽象类,即不可以实例化。纯虚函数是一种特殊的虚函数,在许多情况下,在基类中不能对虚函数给出有意义的实现,而把它声明原创 2015-11-20 23:01:29 · 38403 阅读 · 5 评论 -
没有躲过的坑--获取设备环境HDC
最近在做一个功能,要使用GDI进行简单绘图。首先GDI是什么? 英文为:GraphicsDeviceInterface GDI是Graphics Device Interface的缩写,含义是图形设备接口,它的主要任务是负责系统与绘图程序之间的信息交换,处理所有Windows程序的图形输出。 在Windows操作系统下,绝大多数具备图形界面的应用程序都离不开GDI,我们利用GDI所提供的众多函原创 2015-11-19 23:17:02 · 2779 阅读 · 0 评论 -
没有躲过的坑--正确释放vector的内存
vector的内存会不会泄露? 即使不泄露,怎么能缩小所占空间呢?我们知道vector有个clear()方法?原型:#include <vector>void clear();函数clear()删除储存在vector中的所有元素. 如果vector的元素是一些object, 则它将为当前储存的每个元素调用它们各自的析构函数(destructor). 然而, 如果vector储存的是指向对象的指针原创 2015-11-18 21:20:08 · 9654 阅读 · 1 评论 -
没有躲过的坑--重定义关键字
从学习编程语言开始,我们就知道变量或是函数的命名不能使用系统的关键字。但是有时候,你不得不这么做。比如mac、ios、Android、windows共用一个底层代码,这样为了使底层更加通用,有时候就会忽略某种语言的某个关键字。也许关键字A对于win32就是一个系统关键字,而A不是objective-c的关键字。这个时候为了保证代码的通用性,就需要重定义关键字,也就是所说的屏蔽掉系统关键字。比如对于w原创 2015-11-18 19:59:16 · 3640 阅读 · 1 评论 -
没有躲过的坑--windows下chrome浏览器插件不能安装
在工作和生活中我们往往用到chrome浏览器,也往往需要安装各种各样的插件。很多情况下,你需要安装的插件是自己公司开发,不是出自Google商店,这样你就会遇到很多的坑儿。一般情况下,打开chrome浏览器,按下图1-2-3操作: 正常情况下,你把你需要的空间拖到刚才打开页面的空白处就可以安装了。但是有些插件是不可以的,我们需要寻找另一个办法。假如插件叫123.crx,这个时候,我们修改这个文原创 2015-11-17 21:07:15 · 3308 阅读 · 1 评论 -
没有躲过的坑--wstring与string的转换
wstring 是指的宽字节。typedef basic_string<char> string; typedef basic_string<wchar_t> wstring; 在实际工程中,我们往往需要把string转换为wstring,你可以会进行百度或是Google,很轻松找到转换的方法。但是这里就隐含着巨大的坑儿。 看看这个转换吧:std::wstring WStringToWStrin原创 2015-11-16 22:17:51 · 38113 阅读 · 8 评论 -
没有躲过的坑--string中的c_str()陷阱
string.c_str是Borland封装的String类中的一个函数,它返回当前字符串的首字符地址。c_str函数的返回值是const char*的,不能直接赋值给char*,所以就需要我们进行相应的操作转化。#include <iostream> #include <string> int main() { std::string s = "Chelse"; c原创 2015-11-16 22:02:57 · 11878 阅读 · 0 评论 -
没有躲过的坑--智能指针陷阱
之前博客《浅析C++中的智能指针》讲诉了一些智能指针的东西,可以帮助我们更加方便高效的使用指针,但是凡事都不会很完美。即使你使用智能指针代替了传统的指针,在实战中你还是会遇到很多的坑儿。现在,就分几个方面: 首先为了简化代码,进行了一些定义:class Test{public: Test():m_value(0) { std::cout << "Test::Test" << std::原创 2015-11-15 13:51:34 · 4655 阅读 · 4 评论 -
没有躲过的坑--deprecated关键字
最近两个被一个问题搞的晕晕乎乎,一直把焦点关注在 EXPRESSION SFINAE。因为对我来说,EXPRESSION SFINAE也是完全新鲜的内容,有时间也发个关于这个特性的博客。经历了一番周折,下载最新的VS2015,使用低版本的编译器,都未能解决问题。最后关键字deprecated浮出水面,哎,自惭形秽!利用 deprecated 声明,您可以将函数重载的特殊形式指定为已弃用,而杂注形式适原创 2015-11-03 21:10:47 · 5261 阅读 · 2 评论 -
没有躲过的坑--指针(内存泄露)
C++被人骂娘最多的就是指针。 夜深人静的时候,拿出几个使用指针容易出现的坑儿。可能我的语言描述有些让人费劲,尽量用代码说话。通过指向类的NULL指针调用类的成员函数 试图用一个null指针调用类的成员函数,导致崩溃:#include <iostream>using namespace std;class A { int value;public: void dumb() c原创 2015-11-04 23:47:00 · 3811 阅读 · 3 评论 -
没有躲过的坑--头文件相互包含(Compiler error C2653: not a class or namespace name)
最近被自己坑儿了一把,改别人的代码,最后编译器这样报错的:error C2653: not a class or namespace name简单描述一下: 有一个类A,声明和实现分别位于 a.h和a.cc中 有一个类B,声明和实现分别位于 b.h和b.cc中 类A的某个成员函数需要B类类型作为参数 类B的某个成员函数需要A类类型作为参数a.h文件如下:#ifndef A_H_#defin原创 2015-11-07 00:30:27 · 14758 阅读 · 2 评论 -
没有躲过的坑--获取一张图片的width和height
有时候问题总是被想的过于复杂!简单说就是读取一张图片,然后得到这个图片的width和height。首先,用到的库没有Image这个控件,所以不能从控件获得图片的高和宽。于是GOOGLE了一个算法,稍作修改,对于不同的类型有不同的计算方法,上代码吧:#include<iostream>#include<fstream>using namespace std;int main(){ st原创 2015-11-12 21:46:53 · 2353 阅读 · 2 评论 -
没有躲过的坑--This function or variable may be unsafe.
再说一个坑儿。有时候我们很怀旧,或是喜欢使用一些过时的东西,但是它应该工作的。比如: 判断一个文件是否存在,我们可以使用access。但是access已经是过去时了,用_access代替之。还有很多类似的,这样很不友好。再比如说fopen: 会提示这样的错误:'fopen': This function or variable may be unsafe. Consider using fop原创 2015-11-12 22:10:39 · 1878 阅读 · 1 评论