关于C/C++基础知识的面试题 http://blog.chinaunix.net/uid-25132162-id-362698.html
已知String类定义如下,尝试写出类的成员函数实现。
class String
{
public:
String(const char *str = NULL); // 通用构造函数
String(const String &another); // 拷贝构造函数
~ String(); // 析构函数
String & operater =(const String &rhs);// 赋值函数
private:
char *m_data;// 用于保存字符串
};
答:
String::String(const char *str)
{
if ( str== NULL ) //strlen在参数为NULL时会抛异常才会有这步判断
{
m_data = new char[1] ;
m_data[0] = '\0' ;
}
else
{
m_data = new char[strlen(str) +1];
strcpy(m_data,str);
}
}
String::String(const String &another)
{
m_data = new char[strlen(another.m_data) + 1];
strcpy(m_data,other.m_data);
}
String& String::operator =(const String &rhs)
{
if ( this== &rhs)
return *this ;
delete []m_data;//删除原来的数据,新开一块内存
m_data = new char[strlen(rhs.m_data) + 1];
strcpy(m_data,rhs.m_data);
return *this;
}
String::~String()
{
delete []m_data;
}
交换变量a和b的值:#defineswap(a,b) a=a+b;b=a-b;a=a-b;
变量a和b,不用if、?:、switch或其它判断语句,找出最大的一个变量。
答:( ( a + b) + abs( a- b ) ) / 2
static全局变量与普通的全局变量有什么区别?static局部变量和普通局部变量有什么区别?static函数与普通函数有什么区别?(20分)
static全局变量与普通全局变量的区别:前者在主函数之前就要被初始化,(2分)后者无要求。(2分)
static局部变量和普通局部变量的区别:static全句变量是所有函数共享的变量,在一个函数使用完它后它的值会保持到下一个函数来改变它(2分)。后者,本函数所声明的局部变量在本函数运行完之后会被销毁。(2分)
static函数与普通函数的区别:static的可以用类来访问(就是不用初始化一个类就直接使用这个类的这个static方法);(2分)非static的只能通过对象来访问(2分)。static的定义里不能用到类内部非static变量值。(3分)static在循环中定义并赋值时,定义过程只进行一次,而不是每个循环1次。(3分)
堆:由malloc系列函数或new操作符分配的内存。其生命周期由free或delete决定。在没有释放之前一直存在,知道程序结束。其特点是使用灵活,空间比较大,但容易出错。
栈:保存局部变量。栈上的内容只在函数的范围内存在,当函数运行结束,这些内容也会自动被销毁。其特点是效率高,但空间大小有限。
静态区:保存自动全局变量和static变量(包括static全局和局部变量)。静态区的内容在整个程序的生命周期内都存在,由编译器在编译的时候分配。
描述内存分配方式以及它们的区别?
答:1)从静态区分配:内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在。例如全局变量,static 变量。
2)在栈上创建:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集。
3) 从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new 申请任意多少的内存,程序员自己负责在何时用free 或delete 释放内存。动态内存的生存期由程序员决定,使用非常灵活,但问题也最多。
更详细的讲解:http://www.cnblogs.com/daocaoren/archive/2011/06/29/2092957.html
free释放内存后需要做什么?下一行代码应该怎样写?
被free()掉的指针,我们通常叫野指针,野指针是非常危险的哦,可能导致多次释放内存或者对野指针进行访问,
这两种情况都可能导致严重的安全风险。
最好的也是最简单的解决办法就是在释放后,把指针设置为NULL或者指向另一个合法的对象。
就像这样:
free(ptr);
ptr = NULL;
链表题:一个链表的结点结构。
struct Node
{
int data;
Node *next;
};
typedef struct Node Node;
(1)已知链表的头结点head,写一个函数把这个链表逆序 ( Intel)
Node * ReverseList(Node *head) //链表逆序
{
if ( head== NULL || head->next == NULL )
return head;
Node *p1= head ;
Node *p2= p1->next;
Node *p3= p2->next;
p1->next = NULL ;
while ( p3!= NULL )
{
p2->next = p1 ;
p1 = p2 ;
p2 = p3 ;
p3 = p3->next ;
}
p2->next = p1 ;
head = p2 ;
return head;
}
(2)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序。(保留所有结点,即便大小相同)
Node * Merge(Node *head1 , Node *head2)
{
if ( head1== NULL)
return head2 ;
if ( head2== NULL)
return head1 ;
Node *head= NULL ;
Node *p1= NULL;
Node *p2= NULL;
if ( head1->data < head2->data )
{
head = head1 ;
p1 = head1->next;
p2 = head2 ;
}
else
{
head = head2 ;
p2 = head2->next;
p1 = head1 ;
}
Node *pcurrent= head ;
while ( p1!= NULL && p2!= NULL)
{
if ( p1->data <= p2->data )
{
pcurrent->next = p1 ;
pcurrent = p1 ;
p1 = p1->next ;
}
else
{
pcurrent->next = p2 ;
pcurrent = p2 ;
p2 = p2->next ;
}
}
if ( p1!= NULL )
pcurrent->next = p1 ;
if ( p2!= NULL )
pcurrent->next = p2 ;
return head;
}
(3)已知两个链表head1 和head2 各自有序,请把它们合并成一个链表依然有序,这次要求用递归方法进行。 (Autodesk)
答案:
Node * MergeRecursive(Node *head1 , Node *head2)
{
if ( head1== NULL )
return head2 ;
if ( head2== NULL)
return head1 ;
Node *head= NULL ;
if ( head1->data < head2->data )
{
head = head1 ;
head->next = MergeRecursive(head1->next,head2);
}
else
{
head = head2 ;
head->next = MergeRecursive(head1,head2->next);
}
return head;
}
delete与delete []的区别
答: delete只会调用一次析构函数,而delete[]会调用每一个成员的析构函数。在More Effective C++中有更为详细的解释:“当delete操作符用于数组时,它为每个数组元素调用析构函数,然后调用operator delete来释放内存。”delete与New配套,delete []与new []配套。
下面哪种排序法对12354最快。
quick sort
buble sort(正确)
merge sort
当数据规模较小时,应选择直接插入排序或冒泡排序。任何排序算法在数据量小时基本体现不出来差距。我们说快排好,是指大量随机数据下,快排效果最理想。而不是所有情况。
哪种结构,平均来讲,获取一个值最快。
binary tree
hash table(正确)
stack
死锁产生的原因及四个必要条件
产生死锁的原因主要是:
(1) 因为系统资源不足。
(2) 进程运行推进的顺序不合适。
(3) 资源分配不当等。
如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则
就会因争夺有限的资源而陷入死锁。其次,进程运行推进顺序与速度不同,也可能产生死锁。
产生死锁的四个必要条件:
(1) 互斥条件:一个资源每次只能被一个进程使用。
(2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。
(3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。
(4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。
这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之
一不满足,就不会发生死锁。
【持续更新 10-7】