一、选择题
1、执行以下程序
char *str;
cin >> str;
cout << str;
若输入abcd 1234,则输出(D)
A. abcd B. abcd 1234 C.1234 D. 输出乱码或错误
str是一个char*型指针,未初始化,是一个野指针。所以往该地址输入会coredump;
2、执行以下程序
char a[200];
cin.getline(a, 200, ' ');
cout << a;
若输入abcd 1234,则输出(A)
A. abcd B. abcd 1234 C.1234 D. 输出乱码或错误
cin.getline(char* buf, std::streamsize count,char_type delim = '\n');
buf--->接受cin输入流的对象
count--->最多接受字符书
delim--->接受停止标识符,默认为'\n'
二、解答题
1.new/和delete的工作步骤
new的工作步骤:
1、调用名为operator new的标准库函数,分配足够大的原始的未类型化的内存,以保存指定类型的
一个对象
2、运行该类型的一个构造函数初始化对象
3、返回指向新分配并构造的构造函数对象的指针
delete的工作步骤:
1、调用析构函数,回收对象中数据成员所申请的资源
2、调用名为operator delete的标准库函数释放该对象所用的内存
2.对象的销毁与析构函数的调用是不是等价的?
对于栈对象,本句话是对的,但是对于堆对象而言,析构函数的的调用只是对象销毁中的一个步骤,先去调用对象的析构函数,再去调用operator delete函数来释放自身。
3.创建栈对象的条件是什么?
1.能访问构造函数进行初始化 2.能执行析构函数进行销毁。
**4.标准IOStream,简述4种流的状态,Linux下ctrl+z、ctrl+c,ctrl+d各种代表什么**
4种流的状态:
1.badbit:使用bad函数进行测试,是一个无法恢复的系统级错误
2.failbit:使用fail函数进行测试,是一个可恢复的错误,可以用cin.clear()来重置流的状态,
然后用cin.ignore来清空缓冲区
3.eofbit:使用eof函数进行测试,表明文件指针到达文件末尾
4.goodbit:使用good函数进行测试,表明流的状态是正常的,才可以进行接下来的操作ctrlt+z--->挂起,把进程挂起到后台
ctrl+c---->中断,终止进程
ctrl+d----->表示 EOF,是发送一个exit信号,
5.为什么内存对齐,内存对齐的规则?
为什么内存对齐?------如果不进行内存对齐,访问数据的时候可能会造成二次访问
内存对齐的规则:
1、数据成员对齐规则结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset(偏移)为0的地方,以后每个数据成员的对齐按照 #pragma pack 指定的数值和这个数据成员自身长度中,比较小的那个进行
#pragma pack(8)
struct x
{
char a;
int b;
short c;
char d;
}MyStructX;//12
0 1 2 3 4 5 6 7
a x x x b b b b
c c d x
所以是12
struct y
{
int b;
char a;
char d;
short c;
}MyStructY;//8
0 1 2 3 4 5 6 7
b b b b a d c c --->8,
2、结构(或联合)的整体对齐规则 在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照 #pragma pack 指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
#pragma pack(8)
struct SS
{
int a;
char b;
short c;
int d;
struct FF
{
int a1;
char b1;
short c1;
char d1;
}MyStructFF;
char e;
}MyStructSS;
0 1 2 3 4 5 6 7
a a a a b x c c
d d d d a1 a1 a1 a1
b1 x c1 c1 d1 x x x //FF结构体中最小为int,内存对齐
e x x x
所以是28
3、结构体作为成员如果一个结构里有某些结构体成员,则内部结构体成员要从成员最大元素大小的整数倍和 #pragmapack指定的数值中最小的一个的整数倍的地址开始存储。#pragma pack(n) 对齐系数
struct DD
{
int a;
char b;
short c;
int d;
struct FF
{
double a1;
char b1;
short c1;
char d1;
}MyStructFF;
char e;//40
}MyStructDD;
0 1 2 3 4 5 6 7
a a a a b x c c
d d d d x x x x //FF结构体里面最大的是double,结构体对齐
a1 a1 a1 a1 a1 a1 a1 a1
b1 x c1 c1 d1 x x x //结构体对齐,因此总字节为40
三、编程题
1、分别实现new/delete表达式中只能生成栈对象的代码和只能生成堆对象的代码
a.new/delete工作测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
class Student
{
public:
Student(int id, const char *name)
:_id(id)
, _name(new char[strlen(name) + 1]())
{
cout << "Student()构造函数" << endl;
strcpy(_name, name);
}
~Student()
{
if (_name)
{
delete[]_name;
_name = nullptr;
}
cout << "~Student()析构函数" << endl;
}
void *operator new(size_t sz)
{
cout << "operator new" << endl;
void *ret = malloc(sz);
return ret;
}
void operator delete(void *pointer)
{
cout << "operator delete" << endl;
free(pointer);
}
void print()const
{
cout << "id:" << _id << endl
<< "name:" << _name << endl;
}
private:
int _id;
char *_name;
};
//1.问题1:对象的销毁和执行析构函数是不是等价的?
//--1.对于栈上的对象,是等价的 2.对于堆上的对象,析构函数的调用只是对象销毁的一个步骤,真正的销毁是在operator的delete里
//2.问题2:成员函数operator new和delete是否有this指针 ----没有,operator new/delete 是全局静态函数,全员共享
//3.问题3:将operator new/delete函数放在类外且不加类名与作用域限定符,又会产生什么现象,该如何解释?
void test01()
{
Student *pstu = new Student(100, "Jackie");//1.申请空间 2.调用构造函数 3.返回指针。
pstu->print();
delete pstu;
//Student St = Student(20, "Jerry");
//St.print();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
b.只能在栈中生成对象: 把operator new/delete函数设置成私有
栈对象存在的条件:1.能访问构造函数进行初始化 2.能执行析构函数进行销毁。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
/*
使用new表达式的时候,发生的三个步骤:
1.调用名为operator new的标准库函数,分配足够大的原始未初始化的内存,
2.运行调用类型的一个构造函数来初始化对象
3.返回指向新分配构造函数对象的指针。
使用delete的工作步骤:
1.调用析构函数,回收对象中数据成员所申请的资源
2.调用operator delete 的标准库函数释放该对象所用的内存
*/
class Student
{
public:
Student(int id, const char *name)
:_id(id)
, _name(new char[strlen(name) + 1]())
{
cout << "Student()构造函数" << endl;
strcpy(_name, name);
}
void print()const
{
cout << "id:" << _id << endl
<< "name:" << _name << endl;
}
~Student()
{
if (_name)
{
delete[]_name;
_name = nullptr;
}
cout << "~Student()析构函数" << endl;
}
private:
int _id;
char *_name;
void *operator new(size_t sz)
{
cout << "operator new" << endl;
void *ret = malloc(sz);
return ret;
}
void operator delete(void *pointer)
{
cout << "operator delete" << endl;
free(pointer);
}
};
void test01()
{
//Student *pstu = new Student(100, "Jackie");//1.operator new/delete设置成私有后,用new时会拒绝访问,因此会报错
//pstu->print();
//pstu->destroy();
Student St = Student(20, "Jerry");//
St.print();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
c.只能在堆中生成对象:
1、只需要把析构函数设为私有
2.还需要在类里面第一一个函数来销毁堆对象
3、在类中执行delete this的时候,先去调用析构函数来释放类中的成员,再通过operator delete来释放自身
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
/*
使用new表达式的时候,发生的三个步骤:
1.调用名为operator new的标准库函数,分配足够大的原始未初始化的内存,
2.运行调用类型的一个构造函数来初始化对象
3.返回指向新分配构造函数对象的指针。
使用delete的工作步骤:
1.调用析构函数,回收对象中数据成员所申请的资源
2.调用operator delete 的标准库函数释放该对象所用的内存
*/
class Student
{
public:
Student(int id, const char *name)
:_id(id)
, _name(new char[strlen(name) + 1]())
{
cout << "Student()构造函数" << endl;
strcpy(_name, name);
}
void *operator new(size_t sz)
{
cout << "operator new" << endl;
void *ret = malloc(sz);
return ret;
}
void operator delete(void *pointer)
{
cout << "operator delete" << endl;
free(pointer);
}
void destroy()
{
if (this)
{
delete this;//会跑去调用析构函数,先把成员函数释放掉,再来运行operator delete函数,把自身释放掉
}
}
void print()const
{
cout << "id:" << _id << endl
<< "name:" << _name << endl;
}
private:
int _id;
char *_name;
~Student()
{
if (_name)
{
delete[]_name;
_name = nullptr;
}
cout << "~Student()析构函数" << endl;
}
};
void test01()
{
Student *pstu = new Student(100, "Jackie");//1.申请空间 2.调用构造函数 3.返回指针。
pstu->print();
pstu->destroy();
//Student St = Student(20, "Jerry");//把析构函数放在私有权限下,会error报错
//St.print();
}
int main()
{
test01();
system("pause");
return EXIT_SUCCESS;
}
四、算法题(选做,如果做不出来可以不做)
1、题目:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
#include<string>
class Solution
{
public:
void odd(int *array, int len)
{
int k = 0;
for (int i = 0; i < len; i++)
{
if (array[i] % 2 != 0)
{
int temp = array[i];
array[i] = array[k];
array[k] = temp;
k++;
}
}
}
};
int main()
{
Solution s1;
int array[10] = { 1,2,3,4,5,6,7,8,9,10 };
s1.odd(array,10);
for (int i = 0; i < 10; i++)
{
cout << array[i] << endl;
}
system("pause");
return EXIT_SUCCESS;
}