STL中list,vector,deque,map,set区别、联系和使用场景

2011年3月3日 没有评论

版权声明:本文某些内容来源于互联网,经过自己整理、编辑和总结成文,谢谢csdn,谢谢 google

vector和built-in数组类似,它拥有一段连续的内存空间,并且起始地址不变,因此
它能非常好的支持随即存取,即[]操作符,但由于它的内存空间是连续的,所以在中间
进行插入和删除会造成内存块的拷贝,另外,当该数组后的内存空间不够时,需要重新
申请一块足够大的内存并进行内存的拷贝。这些都大大影响了vector的效率。

list就是数据结构中的双向链表(根据sgi   stl源代码),因此它的内存空间可以是不连续
的,通过指针来进行数据的访问,这个特点使得它的随即存取变的非常没有效率,因此它
没有提供[]操作符的重载。但由于链表的特点,它可以以很好的效率支持任意地方的删除
和插入。

deque是一个double-ended   queue,它的具体实现不太清楚,但知道它具有以下两个特点:
它支持[]操作符,也就是支持随即存取,并且和vector的效率相差无几,它支持在两端的
操作:push_back,push_front,pop_back,pop_front等,并且在两端操作上与list的效率
也差不多。

Map是STL的一个关联容器,它提供一对一(其中第一个可以称为关键字,每个关键字只能在map中出现一次,第二个可能称为该关键字的值)的数据处理能力,由于这个特性map内部的实现自建一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能。

set是集合,set中不会包含重复的元素,这是和vector的第一个区别,第二个区别是set内部用平衡二叉树实现,便于元素查找,而vector是使用连续内存存储,便于随机存取。
因此在实际使用时,如何选择这几个容器中哪一个,应根据你的需要而定,一般应遵循下面
的原则:
1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list
3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。

4、如果你要存储一个数据字典,并要求方便地根据key找value,那么map是较好的选择

5、如果你要查找一个元素是否在某集合内存中,则使用set存储这个集合比较好

参考文献:
1、http://topic.csdn.net/t/20011226/08/442147.html

2、http://41620935.blog.163.com/blog/static/498206420082185032531/

Popularity: 43%

分类: C++ 标签: , , , , , ,

【转】Linux下的段错误产生的原因及调试方法

2011年3月1日 没有评论

编者按:最近用gdb调试程序,发现功能还是比较强大的,下面是gdb调试段错误的一些方法

这篇文章好多地方都有,最早的我看到的是这个,我也是从这里转的:http://www.upsdn.net/html/2006-11/775.html

简而言之,产生段错误就是访问了错误的内存段,一般是你没有权限,或者根本就不存在对应的物理内存,尤其常见的是访问0地址.

一般来说,段错误就是指访问的内存超出了系统所给这个程序的内存空间,通常这个值是由gdtr来保存的,他是一个48位的寄存器,其中的32位是保存由它指向的gdt表,后13位保存相应于gdt的下标,最后3位包括了程序是否在内存中以及程序的在cpu中的运行级别,指向的gdt是由以64位为一个单位的表,在这张表中就保存着程序运行的代码段以及数据段的起始地址以及与此相应的段限和页面交换还有程序运行级别还有内存粒度等等的信息。一旦一个程序发生了越界访问,cpu就会产生相应的异常保护,于是segmentation fault就出现了.

在编程中以下几类做法容易导致段错误,基本是是错误地使用指针引起的

1)访问系统数据区,尤其是往  系统保护的内存地址写数据
最常见就是给一个指针以0地址
2)内存越界(数组越界,变量类型不一致等) 访问到不属于你的内存区域

解决方法

我们在用C/C++语言写程序的时侯,内存管理的绝大部分工作都是需要我们来做的。实际上,内存管理是一个比较繁琐的工作,无论你多高明,经验多丰富,难 免会在此处犯些小错误,而通常这些错误又是那么的浅显而易于消除。但是手工“除虫”(debug),往往是效率低下且让人厌烦的,本文将就”段错误”这个 内存访问越界的错误谈谈如何快速定位这些”段错误”的语句。
下面将就以下的一个存在段错误的程序介绍几种调试方法:

1  dummy_function (void)
2  {
3          unsigned char *ptr = 0×00;
4          *ptr = 0×00;
5  }
6
7  int main (void)
8  {
9          dummy_function ();
10
11          return 0;
12  }

作为一个熟练的C/C++程序员,以上代码的bug应该是很清楚的,因为它尝试操作地址为0的内存区域,而这个内存区域通常是不可访问的禁区,当然就会出错了。我们尝试编译运行它:

xiaosuo@gentux test $ ./a.out
段错误

果然不出所料,它出错并退出了。
1.利用gdb逐步查找段错误:
这种方法也是被大众所熟知并广泛采用的方法,首先我们需要一个带有调试信息的可执行程序,所以我们加上“-g -rdynamic”的参数进行编译,然后用gdb调试运行这个新编译的程序,具体步骤如下:

xiaosuo@gentux test $ gcc -g -rdynamic d.c
xiaosuo@gentux test $ gdb ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB.  Type “show warranty” for details.
This GDB was configured as “i686-pc-linux-gnu”…Using host libthread_db library “/lib/libthread_db.so.1″.

(gdb) r
Starting program: /home/xiaosuo/test/a.out

Program received signal SIGSEGV, Segmentation fault.
0×08048524 in dummy_function () at d.c:4
4               *ptr = 0×00;
(gdb)

哦?!好像不用一步步调试我们就找到了出错位置d.c文件的第4行,其实就是如此的简单。
从这里我们还发现进程是由于收到了SIGSEGV信号而结束的。通过进一步的查阅文档(man 7 signal),我们知道SIGSEGV默认handler的动作是打印”段错误”的出错信息,并产生Core文件,由此我们又产生了方法二。
2.分析Core文件:
Core文件是什么呢?

The  default action of certain signals is to cause a process to terminate and produce a core dump file, a disk file containing an image of the process’s memory  at the time of termination.  A list of the signals which cause a process to dump core can be found in signal(7).

以 上资料摘自man page(man 5 core)。不过奇怪了,我的系统上并没有找到core文件。后来,忆起为了渐少系统上的拉圾文件的数量(本人有些洁癖,这也是我喜欢Gentoo的原因 之一),禁止了core文件的生成,查看了以下果真如此,将系统的core文件的大小限制在512K大小,再试:

xiaosuo@gentux test $ ulimit -c
0
xiaosuo@gentux test $ ulimit -c 1000
xiaosuo@gentux test $ ulimit -c
1000
xiaosuo@gentux test $ ./a.out
段错误 (core dumped)
xiaosuo@gentux test $ ls
a.out  core  d.c  f.c  g.c  pango.c  test_iconv.c  test_regex.c

core文件终于产生了,用gdb调试一下看看吧:

xiaosuo@gentux test $ gdb ./a.out core
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB.  Type “show warranty” for details.
This GDB was configured as “i686-pc-linux-gnu”…Using host libthread_db library “/lib/libthread_db.so.1″.

warning: Can’t read pathname for load map: 输入/输出错误.
Reading symbols from /lib/libc.so.6…done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2…done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./a.out’.
Program terminated with signal 11, Segmentation fault.
#0  0×08048524 in dummy_function () at d.c:4
4               *ptr = 0×00;

哇,好历害,还是一步就定位到了错误所在地,佩服一下Linux/Unix系统的此类设计。
接着考虑下去,以前用windows系统下的ie的时侯,有时打开某些网页,会出现“运行时错误”,这个时侯如果恰好你的机器上又装有windows的编译器的话,他会弹出来一个对话框,问你是否进行调试,如果你选择是,编译器将被打开,并进入调试状态,开始调试。
Linux下如何做到这些呢?我的大脑飞速地旋转着,有了,让它在SIGSEGV的handler中调用gdb,于是第三个方法又诞生了:
3.段错误时启动调试:

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>

void dump(int signo)
{
char buf[1024];
char cmd[1024];
FILE *fh;

snprintf(buf, sizeof(buf), “/proc/%d/cmdline”, getpid());
if(!(fh = fopen(buf, “r”)))
exit(0);
if(!fgets(buf, sizeof(buf), fh))
exit(0);
fclose(fh);
if(buf[strlen(buf) - 1] == ‘\n’)
buf[strlen(buf) - 1] = ‘\0′;
snprintf(cmd, sizeof(cmd), “gdb %s %d”, buf, getpid());
system(cmd);

exit(0);
}

void
dummy_function (void)
{
unsigned char *ptr = 0×00;
*ptr = 0×00;
}

int
main (void)
{
signal(SIGSEGV, &dump);
dummy_function ();

return 0;
}

编译运行效果如下:

xiaosuo@gentux test $ gcc -g -rdynamic f.c
xiaosuo@gentux test $ ./a.out
GNU gdb 6.5
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type “show copying” to see the conditions.
There is absolutely no warranty for GDB.  Type “show warranty” for details.
This GDB was configured as “i686-pc-linux-gnu”…Using host libthread_db library “/lib/libthread_db.so.1″.

Attaching to program: /home/xiaosuo/test/a.out, process 9563
Reading symbols from /lib/libc.so.6…done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2…done.
Loaded symbols for /lib/ld-linux.so.2
0xffffe410 in __kernel_vsyscall ()
(gdb) bt
#0  0xffffe410 in __kernel_vsyscall ()
#1  0xb7ee4b53 in waitpid () from /lib/libc.so.6
#2  0xb7e925c9 in strtold_l () from /lib/libc.so.6
#3  0×08048830 in dump (signo=11) at f.c:22
#4  <signal handler called>
#5  0x0804884c in dummy_function () at f.c:31
#6  0×08048886 in main () at f.c:38

怎么样?是不是依旧很酷?
以上方法都是在系统上有gdb的前提下进行的,如果没有呢?其实glibc为我们提供了此类能够dump栈内容的函数簇,详见/usr/include/execinfo.h(这些函数都没有提供man page,难怪我们找不到),另外你也可以通过gnu的手册进行学习。
4.利用backtrace和objdump进行分析:
重写的代码如下:

#include <execinfo.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>

/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
unsigned char *ptr = 0×00;
*ptr = 0×00;
}

void dump(int signo)
{
void *array[10];
size_t size;
char **strings;
size_t i;

size = backtrace (array, 10);
strings = backtrace_symbols (array, size);

printf (“Obtained %zd stack frames.\n”, size);

for (i = 0; i < size; i++)
printf (“%s\n”, strings[i]);

free (strings);

exit(0);
}

int
main (void)
{
signal(SIGSEGV, &dump);
dummy_function ();

return 0;
}

编译运行结果如下:

xiaosuo@gentux test $ gcc -g -rdynamic g.c
xiaosuo@gentux test $ ./a.out
Obtained 5 stack frames.
./a.out(dump+0×19) [0x80486c2]
[0xffffe420]
./a.out(main+0×35) [0x804876f]
/lib/libc.so.6(__libc_start_main+0xe6) [0xb7e02866]
./a.out [0x8048601]

这次你可能有些失望,似乎没能给出足够的信息来标示错误,不急,先看看能分析出来什么吧,用objdump反汇编程序,找到地址0x804876f对应的代码位置:

xiaosuo@gentux test $ objdump -d a.out
8048765:       e8 02 fe ff ff          call   804856c <signal@plt>
804876a:       e8 25 ff ff ff          call   8048694 <dummy_function>
804876f:       b8 00 00 00 00          mov    $0×0,%eax
8048774:       c9                      leave

我们还是找到了在哪个函数(dummy_function)中出错的,信息已然不是很完整,不过有总比没有好的啊!
后记:
本文给出了分析”段错误”的几种方法,不要认为这是与孔乙己先生的”回”字四种写法一样的哦,因为每种方法都有其自身的适用范围和适用环境,请酌情使用,或遵医嘱。

对于段错误这种问题。可以分析以下原因:
(1):指针非法,比如使用没有初始化的指针(没有为此指针指向的对象分配空间),或着Free掉之后再次使用。
(2):数组访问越界,访问的元素下标超过数组围长
(3):缓存溢出,对于这种while(1) {do}的程序,这个问题最容易发生,多此sprintf或着strcat有可能将某个
buff填满,溢出,所以每次使用前,最好memset一下,不过要是一开始就是段错误,而不是运行了一会儿出现的,(3)的可能性就比较小。

Popularity: 13%

分类: C++, linux 标签:

番茄工作法 (提供下载)

2011年1月9日 1 条评论

最近使用番茄工作法,对提高效率非常有好处。

Pomodoro Technique™番茄工作法是由Francesco Cirillo弗朗切斯科•齐立罗于1992年发明的。它的作用在于时间管理。它能帮助你让时间成为你最好的伙伴,让你在做事情时的效率提升一个档次。

花上几分钟时间阅读一下这里的信息和手册,以及下载免费电子书PDF,你就可以轻松得开始使用番茄工作法了。你正在找寻一些额外的动力和灵感 吗?我们独家的番茄套装,包括25分钟番茄计时器、T恤、铅笔、TO DO TODAY工作计划表。

请准备以下材料:

一个计时器——厨房计时器。想要我们的独家计时器吗?订购我们的25分钟番茄计时器。

一张工作表。正在寻找独家的番茄工作表吗?

一支铅笔

一外加一个橡皮擦!

改善注意力,每25分钟重复一次下列步骤:

1、选择一个要完成的任务

2、将番茄钟设定为25分钟,番茄钟即闹铃

3、开始工作直到番茄计时器响起,然后检查一下计划表

4、略作休息(约5分钟为宜)

5、进行四次番茄工作法后休息略长的一段时间

番茄留言板

华尔街日报

“这个离奇的方法强烈地刺激着我的工作,这个方法来源于依靠时间管理工具和技术让事情变得简单,高频率的休息间隙可以提高人们智力 的敏捷,同时也可以改变人们对于时间的看法,缓解对时间的焦虑,释放焦虑就可以更好的集中精力”—— Sue Shellenbarger

非官方的苹果博客

“这个方法真的是太简单,太容易去做,而且实在是太有效了啊!”——Steven Sande

Lifehacker.com

番茄工作法提供了一个旨在消除与截止日期相关的焦虑的循环系统——Kevin Purdy

下载地址:番茄工作法

Popularity: 29%

分类: 生活 标签:

又周五了,讲个笑话听听

2010年12月17日 没有评论

昨天去上瑜伽课,瑜伽老师是个印度人,中文说的不是太好,有些动作讲解的不是很清楚。课罢,我主动跑去找老师请教一个动作的细节。

讨论完后 ,一个新同学紧跟着问了一个问题:“老师,我也有地方听不太懂。”

老师:“哪里有问题?”

新同学不解:“为什么在冥想休息的时候您讲到“反思你的脚趾,反思你的膝盖,反思你的膝盖窝……?我不知道脚趾怎么会反思,膝盖怎么样反思…..” : :shock:

老师:“Urh…就是要反思。”  :(

我在旁边扑哧一下笑了,解释说 :”老师讲的是放松你的脚趾,放松你的膝盖……是放松功,不用反思啦…….”   :-D

后面加了一次”Relax”

老师和同学都笑了…..

:-D :-D :-D :-D :-D :-D :-D :-D

Popularity: 7%

分类: 未分类 标签:

分享一本推荐系统的好书Recommender Sytems Handbook(提供下载)

2010年12月16日 2 条评论

单独讲推荐系统的书非常少,最近看到Recommender Sytems Handbook,感觉非常不错,如果有研究推荐系统的朋友可以下载(下载链接在文章最后)。这本书主要分成五个部分:

第一部分:介绍构建推荐系统的基础理论,比如协作过滤,基于内容的过滤,数据挖掘方法和上下文感知的方法;

第二部分:介绍评估推荐系统的方法,构建实际的推荐系统需要考虑的问题;

第三部分:介绍实际的推荐系统的界面展现相关内容

第四部分:介绍了推挤系统的一个新主题,协作推荐,挖掘UGC相关的内容构建一个新的和更加可靠的推荐系统。

第五部分:介绍了推荐系统相关的一些新的paper,包括推荐系统的对恶意攻击的鲁棒性,收集用户更多的信息和反馈提供更可靠的推荐。

下载地址: Recommender Sytems Handbook

Popularity: 57%

分类: 推荐系统 标签:

今日读曾国藩家书两篇

2010年12月11日 没有评论

亮仔一直要求”修身,齐家,治国,平天下”,要“有恒”,所以要加强读书了。
今天读曾国藩家书两篇:篇一,讲到其“唯不耐久思,思多则头晕。故常冥心于无用,优游涵养,以谨守父亲保身之训”,联想起刚刚开始学习的瑜伽冥想,似乎同出一辙,觉得很是神奇,那时候曾父居然传授冥想的方法给曾国藩作为修身养性保身之训。比较受启发,坚定了学习瑜伽功法的决心。 因这两篇主要以家事为主题,篇二仍然提到保身之训“节劳节欲节饮食”,与当前倡导的饮食健康,保持记忆力持久及身体康健有相似之处,目前主张平日正餐7-8成饱。

Popularity: 6%

分类: 未分类 标签:

实现c++中类似php的explode函数

2010年11月27日 没有评论

20110316更新:发现自己太土了,居然不知道有strtok 这么一个函数,可以实现类似的功能。 strtok 函数描述如下:(下面英文内容,完全来自于http://www.cplusplus.com/reference/clibrary/cstring/strtok/ ,更多内容和代码示例参加此处)

char * strtok ( char * str, const char * delimiters );

Split string into tokens
A sequence of calls to this function split str into tokens, which are sequences of contiguous characters separated by any of the characters that are part of delimiters.

On a first call, the function expects a C string as argument for str, whose first character is used as the starting location to scan for tokens. In subsequent calls, the function expects a null pointer and uses the position right after the end of last token as the new starting location for scanning.

To determine the beginning and the end of a token, the function first scans from the starting location for the first character not contained in delimiters (which becomes thebeginning of the token). And then scans starting from this beginning of the token for the first character contained in delimiters, which becomes the end of the token.

This end of the token is automatically replaced by a null-character by the function, and the beginning of the token is returned by the function.

Once the terminating null character of str has been found in a call to strtok, all subsequent calls to this function with a null pointer as the first argument return a null pointer.

Parameters

str
C string to truncate. The contents of this string are modified and broken into smaller strings (tokens).
Alternativelly, a null pointer may be specified, in which case the function continues scanning where a previous successful call to the function ended.
delimiters
C string containing the delimiters.
These may vary from one call to another.

Return Value

A pointer to the last token found in string.
A null pointer is returned if there are no tokens left to retrieve.

—————————-我是华丽的分界线—————————————————————
写习惯了php,发现explode很好用,而c++中没有,写了一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
vector<string> explode(const char * probe,  char * data)
{
 string dataStr(data);
 int pos1 = 0;
 int pos2 = 0;
 vector<string> result;
 while((pos2=dataStr.find(probe,pos1)) != string::npos){
 result.push_back(dataStr.substr(pos1,pos2-(pos1+1)));
 pos1=pos2+1;
 }
 result.push_back(dataStr.substr(pos1));
 return result;
}

Popularity: 12%

分类: 开源, C++ 标签:

闭上眼睛,深深呼吸,桂花好香,心醉了…

2010年11月14日 1 条评论

花香是无私的,整个城市都沉浸在桂花的香味中,无需寻她的源头,每颗树,每个枝,每朵花,都美美地贡献了一股香;

拾级而上,偶尔浓郁的桂花香总是逗着人想寻着味去找她,若即若离,找到了,深吸几口气,贪婪而又不舍地继续前行。

将这个人交给空气,交给花香,回到住处的时候发现衣服上,头发上散发着淡淡的花香,开心地笑了……

10月9-10 杭州行

费心做了一个相框,属于桂花

树上的

伸出的枝,根部就张满了桂花,像女孩子裙子的苞花袖

相对叶子,花看起来小小的,但整簇也成规模

桂花树 随处可见

落花满地

落花满地,沉醉,惊叹

花溪

窗前,花墙,树下

:) 让人羡慕,满手小花

特逗,落花有意,人有情


无觅相关文章插件

Popularity: 5%

分类: 未分类 标签:
WordPress Loves AJAX