填空题里有
有一道题是考sizeof的值的,传给sizeof的参数主要是数组名,指针啥的。
写出至少三种STL数据结构:_________;
map , vector , set ,
C++ STL中标准关联容器set, multiset, map, multimap内部采用的就是一种非常高效的平衡检索二叉树:红黑树,也成为RB树(Red-Black Tree)。RB树的统计性能要好于一般的平衡二叉树(有些书籍根据作者姓名,Adelson-Velskii和Landis,将其称为AVL-树),所以被STL选择作为了关联容器的内部结构。
c++定义一个空类,系统会自动生成四种函数,默认构造函数,析构函数,赋值函数和_________;
有时你在设计类时,并不考虑类的constructor,或是destructor,或是assignment
operator。如果你不提供这些类函数,编译器会自动提供这些函数给你。编译器自动提供:
1.
constructor;
2. copy constructor;
3. destructor;
4.
assignment operator ("=");
5.
address_of()
obj是用c++定义的一个类,有obj object = new
obj[100];现在想释放掉所有资源,应写的语句是___delete[]
object;_____;
A* pa = new A(3);
那么上述动态创建一个对象的过程大致相当于以下三句话(只是大致上):
A* pa = (A*)malloc(sizeof(A));
pa->A::A(3);
return pa;
虽然从效果上看,这三句话也得到了一个有效的指向堆上的A对象的指针pa,但区别在于,当malloc失败时,它不会调用分配内存失败处理程序new_handler,而使用new的话会的。因此我们还是要尽可能的使用new,除非有一些特殊的需求。
简答题里有
写出memcpy memset strcpy的作用和区别
(1) Memset
原型: extern void *memset(void *buffer, int c, int count);
用法: #include <string.h>
功能: 把buffer所指内存区域的前count个字节设置成字符 c。
说明: 返回指向buffer的指针。用来对一段内存空间全部设置为某个字符
例如:
char a[10];
memset(a, '/0', sizeof(a));
memset可以方便的清空一个结构类型的变量或数组。
如:struct _test{ char s[10];
int x;
int y;
};
变量 struct _test st;
(1)一般清空st的方法如下:
st.s[0] = '/0'; st.x =0; st.y =0;
(2) 用memset方法如下:
memset(&st,0,sizeof(struct _test));
数组: struct _test st[10];
memset(st,0,sizeof(struct _test)*10); //清空方法
(2)memcpy
原型:extern void *memcpy(void*dest,void*src,unsignedintcount); 用法: #include <string.h>
功能: 由src所指内存区域复制count个字节到dest所指内存区域。
说明: src和dest所指内存区域不能重叠,函数返回指向dest的指针.可以拿它拷贝任何数据类型的对象。
例如: char a[10],b[5];
memcpy(b, a, sizeof(b)); /*注意如果用sizeof(a),会造成b的内存地址溢出*/
(3) Strcpy
原型: extern char *strcpy(char *dest,char *src);
用法: #include <string.h>
功能: 把src所指由NULL结束的字符串复制到dest所指的数组中。
说明: src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳 src的字符串.返回指向dest的指针。
例如: char a[100],b[50];
strcpy(a,b);
如用 strcpy(b,a);
要注意a中的字符串长度(第一个‘/0’之前)是否超过50位,如超过,则会造成b的内存地址溢出。
假如有如下代码,请问输出为多少?
#include
"stdio.h"
main()
{ char
dest[3];
char str[6]="Hello";
strcpy(dest,str);
printf("%s/n",dest);
}
编译输出如下结果:
Hello //没有输出乱码,有点怪怪的为什么?
分析:
1>str中字符串的长度大于dest 的内存长度3.为什么str字符串还能完拷贝到dest 中呢?
来看看 strcpy的 源代码实现:
char *strcpy(char *strDest,const
char *strSrc)
{
assert((strDest!=NULL)&&(strSrc
!=NULL)) //判断指针是否合法,即分配内存,指向某块确定区域
char *address =
strDest; //记住目标地址的起始值
while((*strDest++ =
*strSrc++)!='/0') //先拷贝,后判断,这样就不用在拷贝完了后,再加一句
NULL; // *strDest = '/0';
-->即加一个结束符.因为字符串结束已拷贝了.
return address;
//返回目标首地址的值。
}
//从上面的代码可以看出,strcpy函数,假定strDest的内存空间是足够可以放下strSrc的内容的.
//也就是说使用者,在使用strcpy函数时,应使 (strDest内存空间)>= (strSrc内存空间)
// 在调用 strcpy(dest,str); 时,while((*strDest++ = *strSrc++)!='/0') 没有判断strDest的内存是否够,而是将srtSrc的内容直接拷贝到strDest,当拷到'/0'就结束.
//因此在使用printf("%s/n",dest); 时 输出遇到'/0'时停此输出.所以会输出: Hello
(4) 三者区别
memset 主要应用是初始化某个内存空间。
memcpy 是用于copy源空间的数据到目的空间中。
strcpy 用于字符串copy,遇到‘/0’,将结束。
如果理解了这些,就能知道它们的区别:
例如初始化某块空间的时候,用到memcpy,那么就显得笨拙
int m[100]
memset((void*)m,0x00,sizeof(int*100); //Ok!
memcpy((void*)m,"/0/0/0/0....",sizeof(int)*100); //Not Ok
一.函数原型
strcpy extern char *strcpy(char *dest,char *src);
#include <string.h>
功能:把src所指由NULL结束的字符串复制到dest所指的数组中
说明: src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。 返回指向dest的指针
memcpy extern void *memcpy(void *dest,void *src,unsigned int count);
#include <string.h>
功能:由src所指内存区域复制count个字符串到dest所指内存区域.
说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针.
memset extern void *memset(void *buffer,int c,int count);
#include <string.h>
功能:把buffer所指内存区域的前count个字节设置成字符c
说明:返回指向buffer的指针.
二.区别
memset 用来对一段内存空间全部设置为某个字符,一般用于在对定义的字符串初始化为' '或者'/0';
例: char a[100]; memset(a,'/0',sizeof(a));
memcpy 是用来做内存拷贝,可以用来拷贝任何数据类型的对象,可以指定拷贝的数据长度;
例: char a[100],b[50];
memcpy(b,a,sizeof(b));
//注意:如果使用sizeof(a),会造成内存溢出
mem是一段内存,他的长度,必须自己记住.memcpy是见着什么拷贝什么。
strcpy 就只能拷贝字符串,它遇到'/0'就结束拷贝;
例:char a[100],b[50]; strcpy(a,b);
如用strcpy(b,a)要注意a中的字符串长度(第一个'/0'之前) 是否超过50,如果超过,则会造成b的 内存溢出.
它是不会拷贝'/0'的,所以一般还有加一个语句: *a='/0';
三.使用技巧
memset 可以方便的清空一个数据结构的变量或数组.
如: struct sample_struct {
char csName[16];
int iSeq;
int iType;
};
对于变量
struct sample_struct stTest;
一般情况下,初始化stTest的方法:
stTest.csName[0]='/0';
stTest.iSeq=0;
stTest.iType=0;
而用memset:
memset(&stTest,0,sizeof(struct sample_struct));
如果是数组:
struct sample_struct TEST[100];
memset(TEST,0,sizeof(struct sample_struct)*100);
堆:由程序员自己分配释放(用malloc和free,或new和delete) ,如果我们不手动释放,那就要到程序结束才释放。如果对分配的空间在不用的时候不释放而一味的分配,那么可能会引起内存泄漏,其容量取决于虚拟内存,较大。
栈:由编译器自动分配释放,其中存放在主调函数中被调函数的下一句代码、函数参数和局部变量,容量有限,较小。
静态存储区:由在编译时由编译器分配,由系统释放,其中存放的是全局变量、static变量和常量.
区别:
1)堆是由低地址向高地址扩展,栈是由高地址向低地址扩展。
2)堆是不连续的空间,栈是连续的空间。
3)在申请空间后,栈的分配要比堆的快。对于堆,先遍历存放空闲存储地址的链表、修改链表、再进行分配;对于栈,只要剩下的可用空间足够,就可分配到,如果不够,那么就会报告栈溢出。
4)栈的生命期最短,到函数调用结束时;静态存储区的生命期最长,到程序结束时;堆中的生命期是到被我们手动释放时(如果整个过程中都不手动释放,那就到程序结束时)。
5)举例:
void fun()
{
char *ptr="abcdefg"; //指针变量ptr存在栈空间, 字符串常量"abcdefg”存在静态存储区
char arr[]="abcdef"; //字符数组变量arr(其值"abcdef")存在栈空间
char cha1='x'; //字符变量cha1存在栈空间
char cha2='y'; //字符变量cha2存在栈空间
char *p_char1 ; //字符指针变量p_char1存在栈空间
char *p_char2; //字符指针变量p_char2存在栈空间
p_char1 = arr; //p_char1指向栈空间
p_char2=(char*)new char[10]; //分配10字节的堆空间,p_char2指向这块堆空间
}
注意:在申请到堆空间,用完之后要及时释放,以免引起内存泄漏。
重载和重写的区别
重写是子类的方法覆盖父类的方法,要求方法名和参数都相同
重载是在同一个类中的两个或两个以上的方法,拥有相同的方法名,但是参数却不相同,方法体也不相同,最常见的重载的例子就是类的构造函数,可以参考API帮助文档看看类的构造方法
表名为table的表内容如下
Year month value 2009 1 1.1 2009 2 1.2 2009 3 1.3 2009 4
1.4 2010 1 2.1 2010 2 2.2 2010 3 2.3 2010 4 2.4
要求查询结果为
yearm1 m2 m3 m4 2009 1.1 1.2 1.3 1.4 2010 2.1 2.2 2.3 2.4
编程题里有
双向循环链表 实现它的删除操作
/*创建长度为n的双向循环链表,值为整数。
查找第k个元素并输出。
删除所有值为m的元素。
逆置链表并输出。
*/
int
n;
typedef struct str
{
int num;
struct str *pre;
struct str
*next;
}node;
void creat(node * h)
{
node *c,*r;
r=h;
cout<<"输入链表的长度: ";
cin>>n;
for(int
i=0;i<n;i++)
{
c=(node
*)malloc(sizeof(node));
cout<<"输入数值:
"<<endl;
cin>>c->num;
r->next=c;
c->pre=r;
r=c;
}
r->next=h->next;
h->next->pre=r;
}//..................
void
select(node *h,int k)
{
node
*p;
p=h->next;
if(k>n)
cout<<"errer."<<endl;
else
{
for(int i=1;i<k;i++)
{
p=p->next;
}
cout<<"第"<<k<<"个元素的值为:
"<<p->num<<endl;
}
}
void Delete(node *h,int
m)
{
node
*p,*q;
q=h;
p=h->next;
while(p->next!=h->next)
{
if(h->next->num==m)
//删除首结点
{
h->next=p->next;
p->pre->next=p->next;
p->next->pre=p->pre;
free(p);
p=q->next;
}
else if(p->num==m)
//删除中间结点
{
q->next=p->next;
p->next->pre=q;
free(p);
p=q->next;
}
else
{
q=p;
p=p->next;
}
}
if(p->num==m) //删除尾结点
{
q->next=p->next;
p->next->pre=q;
free(p);
}
}
memcpy函数的函数体实现
再来看Linux中实现:
void *memcpy(void *dest, const void *src, size_t
count)
{
char *tmp = dest;
const char *s = src;
while (count--)
*tmp++ = *s++;
return
dest;
}
第三道是根据已给文字信息和代码,填写五处代码。
C++中有堆,栈和静态存储区,他们的作用和区别。