C++学习之第五天
2021/10/30 22:10:12
本文主要是介绍C++学习之第五天,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
一、选择题
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; }
这篇关于C++学习之第五天的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享