【C++入门攻略】和【编程常见问题】

news/2025/2/13 1:52:33/

常见问题

vsstudio快捷键

快速注释组合键 ctrl+k + ctrl+c

取消注释快捷键 ctrl+k + ctrl + u

支持垃圾回收机制

大多数面向对象编程语言具有垃圾回收机制。早期的C++语言不具备垃圾回收机制,这意味着申请的内存资源在使用完成后,需要程序员自己释放。直到C++11标准诞生,提出了智能指针新特性,实现了内存资源的自动管理,使得指针的使用更加灵活,并避免了内存泄漏问题。

iostream和命名空间std的作用?

iostream

std 就是一个命名空间,对象函数很多都是在这里面定义的 用之前调用

三种方式:

1)using namespace std; //引用标准命名空间std

using std::cout;
using std::endl;

std::cout << “123\n”<<std::endl;;

#include<bits/stdc++.h>
#include<iostream> //标准输入/输出头文件iostream
using namespace std; //引用标准命名空间stdint main()
{cout << "hello" << endl;//cout是预定义的输出流对象,用于输出数据//endl表示换行return 0;
}

或者如果不使用命名空间std;

using std::cout;
using std::endl;

效果相同

#include<bits/stdc++.h>
#include<iostream>
//using namespace std;
using std::cout;
using std::endl;
int main()
{cout << "123\n";return 0;
}

cout和endl的功能?

cout是c++语言的输出符号。endl是程序的结束符。

cout<<endl是使程序输出结束(有使输出结果换行的功能)

iostream.h是什么?

一个非标准的输入输出流 .h的头文件是c语言格式的

和iostrem的区别是存不存在在std命名空间中

iostream是什么?

是标准输入输出流,C++规范的,带有名称空间的头文件 包含在std名字空间中

而iostream流里面又包含cin和cout输入输出对象,所以使用cout的时候必须加std::

通过刚才的比较我们了解到iostream是c++的头文件,而iostreamh是C语言格式的头文件,由于C++格式的iostream是规范的带有名字空间的头文件,所以在使用iostream标准库中的cout对象时要加上名字空间标识符std,而c格式的非标准的输入输出流iostream.h则不用

也就是说从C++开始方才真正引入了名字空间这个新概念,那么名字空间的作用究竞是什么呢?

C++里引入名字空间(namespace)的目的是为了避免和减少命名冲突。一旦一个程序写大了,就很难避免重名,特别是多人合作的情况下。过去C中的解决方法只有靠人为的注意,并自加长名学,以避免重名。这样做会使得一些名字看上去没有意义或者难以理解,而程序员在写程序的时候,也受这个问题的限制,不能自由地命名自己使用的变量或者函数。而有了名字空间(namespace)就不存在这些问题了,这就是C++引入namespace这个概念的好处。

举一个形象的例子

有两个学生,一个叫小王,一个叫小李,他们都各自拥有一本相同的语文书,为了区分这两本书,他们就要在书的封皮上写上自己的名字一小王或者小李。同理,我们调用 cout 对象时也要在前边写上 cout 所属的命名空间“std::”,而在代码里加“using namespace std”,就可以不用再加“std::”。但是最好的方法就是不用“using namespace std”,而是用using std::cout;这样可以避免命名重复,因为不同的名字在不同的命名空间内,将它们都释放出来时,若不小心会造成使用错误库函数中的对象的情况。

在这里插入图片描述

重名问题(多个命名空间)

#include<bits/stdc++.h>
#include<iostream>namespace a
{int b = 1;
}
namespace c {int b = 2;
}
int main()
{/*此处可以不使用using就可直接调用using namespace a;using namespace c;*///此处无法成功调用,因为无法判断调用的是哪个bstd::cout << b;int b = 9;std::cout << b << " " <<a::b<< " " << " " << c::b << " " << std::endl;
}

判断数据类型typeid().name()

cout << typeid(today).name() << endl;

制表符\n\t\r

\n:表示换行操作,光标会移动到下一行(next line)

\t:表示水平制表空行操作,相当于Tab键,不会换行

\r:相当于回车,相当于光标回到本行首位置,不会换行;

函数

函数、输入、传参

在程序中使用函数时,你必须先声明它然后再定义声明的目的是告诉编译器你即将要定义的函数的名字是什么,返回值的类型是什么以及参数是什么而定义则是告诉编译器这个函数的功能是什么。假如我们不声明,那么该函数就不能被其他函数调用通常我们把函数声明叫做函数原型,而把函数定义叫函数实现。

#include<bits/stdc++.h>
using namespace std;
using std::cout;
using std::endl;
void  show()
{int lf = 123;std::cout << "hello world";//return lf;
}
void lf(string name, int age)
{   cout << name << age << endl;
}
int count(int a, int b)
{return a + b;
}
int main()
{//show();//std:cout << s << endl;lf("lf", 12);cout <<count(1,2) << endl;int a, b;cout << "请依次输入两个数字进行求和:"<<endl;cin >> a; //用a保存接受用户输入cin >> b;cout << count(a, b) << endl;return 0;
}

函数声明

在程序中使用函数时,你必须先声明它然后再定义声明的目的是告诉编译器你即将要定义的函数的名字是什么,返回值的类型是什么以及参数是什么而定义则是告诉编译器这个函数的功能是什么。假如我们不声明,那么该函数就不能被其他函数调用通常我们把函数声明叫做函数原型,而把函数定义叫函数实现。

先声明再调用就不会出现找不到的情况,只要声明了就会保存在内存空间,直到找到函数的实现

#include<bits/stdc++.h>
using namespace std;void A();
void B();
void A()
{cout << "A\n";B();
}
void B()
{cout << "B\n";A();
}
int main()
{A();B();return 0;
}

局部变量

只能存活在swap函数之内,swap结束之后,swap函数内的局部变量也就被销毁掉了

因此具体的交换只能反映再swap函数之内,而不能反映在swap函数之外

#include<bits/stdc++.h>
using namespace std;void swap(int, int);
int main()
{int x = 3, y = 4;cout << " main before"<<x << y << endl;swap(x, y);cout << " main after" << x << y << endl;return 0;
}
void swap(int x, int y)
{cout << "swap  before" << x << y << endl;int c = x;x = y;y = c;cout << "swap  after" << x << y << endl;
}

全局变量

#include<bits/stdc++.h>
using namespace std;void swap(int, int);
int x = 3, y = 4;
int main()
{int x = 3000, y = 4000;cout << " main before"<<x << y << endl;swap(x, y);cout << " main after" << x << y << endl;return 0;
}
void swap(int x, int y)
{cout << "swap  before" << x << y << endl;int c = x;x = y;y = c;cout << "swap  after" << x << y << endl;
}

数据的类型

字符型

#include<bits/stdc++.h>
using namespace std;int main()
{char ch = 65;cout << ch << endl;cout << (int)ch;for (int i = 32; i < 128; i++){cout << (char)i << endl;}return 0;
}

双字节型

#include<bits/stdc++.h>
#include<locale>
using namespace std;int main()
{//设置所有的为中文类型setlocale(LC_ALL,"chs");wchar_t wt[] = L"中";//wcout代替cout进行输出,因为cout无法输出宽字节型wcout << wt;return 0;
}

整型

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jKIY4dvi-1684055034018)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20230513183722133.png)]

#include<bits/stdc++.h>
#include<locale>
using namespace std;int main()
{cout << sizeof(int) << endl;cout << sizeof(short) << endl;cout << sizeof(long) << endl;unsigned int a;cout << sizeof(unsigned int) << endl;unsigned short b;cout << sizeof(unsigned short) << endl;unsigned long c;cout << sizeof(unsigned long) << endl;return 0;
}

数据溢出

从该程序中我们看出整型数据溢出后不会报错,而是象汽车里程表那样,到达最大值后,又从最小值开始因此我们需要时刻注意所定义变量的最大取值计数。范围,一定不要超过这个范围进行赋值。

在这里插入图片描述

在这里插入图片描述

浮点型

使用了头文件iomanip 中的函数 setprecision(),该函数用来设置输出的精度也就是用来设置输出多少位数字,

假如我们将其设置为 15,那么程序就将输出 15 位数字,即使不够,也要凑够15位并输出。

#include<bits/stdc++.h>
#include<iomanip>
using namespace std;int main()
{float a = 1.2342421;cout << setprecision(15) << a;return 0;
}

枚举型常量

#include<bits/stdc++.h>
#include<iomanip>
using namespace std;int main()
{enum num { zero = 1, one, two = 200,three,four };cout << zero << "\t" << one << "\t" << two << "\t" << three << "\t" << four;return 0;
}

用enum定义了一个枚举型常量day:它有7个值,每个值对应一个整数从0开始计数,这样星期一(Monday)的值为1,

而星期六(Saturday)的值则为6。

#include<bits/stdc++.h>
#include<iomanip>
using namespace std;int main()
{enum day { Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Satuday };day today;//创建一个变量todaytoday = Monday;cout << today; //输出为1if (today == Satuday || today == Sunday) {cout << "休息\n";}else{cout << "上班\n";}return 0;
}

数组

逆序题

交换位置,只需要交换一半的位置就可以了

#include<bits/stdc++.h>
#include<iomanip>
//#include <typeinfo>
using namespace std;int main()
{int arr[] = {1,2,3,4,5};int temp = 0;int length = sizeof(arr) / sizeof(int);int end = sizeof(arr) / sizeof(int) - 1;for (int i = 0; i < length/2; i++){temp = arr[i];arr[i] = arr[end];arr[end] = temp;end--;}for (int t : arr) {cout << t << " ";}return 0;
}

二维数组题目

#include<bits/stdc++.h>
#include<iomanip>
//#include <typeinfo>
using namespace std;int main()
{//建立二维数组(初始化)int scores[3][3];string names[3] = { "张三","李四","王五" };//赋三科分数int a = 0;int b = 0;int c = 0;//计数(下标)int n = 0;int m = 0;//总分int sum[3];do {cout << "请分别输入" << names[n] << "的三科成绩:" << endl;cin >> a >> b >> c;sum[n] = a + b + c;scores[n][m++] = a;scores[n][m++] = b;scores[n][m] = c;m = 0;//置为0n++;cout << endl;} while (n < 3);//输出for (int i = 0; i < 3; i++) {cout << names[i] << "的总成绩为" << sum[i] << endl;}return 0;
}

面向对象(类)

#include<bits/stdc++.h>
#include<iomanip>
//#include <typeinfo>
using namespace std;
class Human
{
public:void walk() { cout << "walk\n"; };void speak() { cout << "speak\n"; };void run() { cout << "run\n"; };void eat() { cout << "eat\n"; };
};int main()
{Human lf;lf.walk();lf.speak();lf.run();lf.eat();return 0;
}

指针

#include<bits/stdc++.h>
using namespace std;int main() {int i = 1;//cout << &i ;int a  = 1;int* p;p = &a;cout << &a << " " << p << " " << *p<<" " << a<<endl;cout << "--------------------"<<endl;return 0;
}
#include<bits/stdc++.h>
using namespace std;int main() {int i = 1;int* p = 0;cout << &i <<" " << i <<" " << &p<< " " << p;return 0;
}

创建堆

C++中使用关键字new创建一个堆并分配内存

#include<bits/stdc++.h>
using namespace std;
typedef unsigned short int ut;int main() {int* p = new int;*p = 4;cout << *p;return 0;
}

请不要再次对该指针进行删除,因为它所指向的内存区域已经被释放,如果再进行释放,将会使程序崩溃。不过,假如我们将该指针赋为0的话,那么删除一个空指针将是安全的

#include<bits/stdc++.h>
using namespace std;
typedef unsigned short int ut;int main() {int* p = new int;delete p;p = 0;delete p;
}
#include<bits/stdc++.h>
using namespace std;
typedef unsigned short int ut;int main() {int* p = new int;*p = 3600;cout << *p << endl;delete p;cout << *p << endl;p = 0;p = new int;*p = 8;cout << *p << endl;delete p;return 0;
}

内存泄漏

就会造成内存泄露,这是因为,第 1行定义了一个指针p 并使其指向一块内存空间,第2行又将一块新的内存空间的地址赋给了 P。这样第1行所开的那块内存空间就无法再使用了因为指向它的指针现在已经指向了第2块空间。
指针变量p只能保存一个地址,如对它重新赋值,则表示以前的地址被覆盖,假如该地址的内存空间没有被释放,那么你将无法再次通过指针p 访问它是第2块内存的地址

	int* p = new int;delete p;p = new int;

this指针

学生在发新课本时一般都要将自己的名字写在课本上,以说明该课本是自己的,避免与其他人的混淆。对象也要在属于自己的每个成员身上写下自己的名字,以证明该成员是自己的成员,而不是其他对象的成员。this 变量帮助对象做到这一点this 变量记录每个对象的内存地址然后通过间接访问运算符->访问该对象的成员。例程如下:

#include<bits/stdc++.h>
using namespace std;class A
{
public:int get() { return i; }void set(int x) {this->i = x;cout << this << endl;}
private:int i;
};
int main() {A a;a.set(9);cout << a.get() << endl;A b;b.set(10);cout << b.get() << endl;return 0;
}

引用

引用的作用

引用在C++中有以下几个主要作用:

  1. 别名: 引用允许我们创建变量的别名,可以通过不同的名称来访问同一变量或对象,从而使代码更加灵活易读。
  2. 函数参数传递: 通过将函数参数声明为引用,函数可以直接修改调用者传递的变量,而无需使用指针或复制数据。这种方式避免了对大型结构体或对象进行值传递时的开销,提高程序效率。
  3. 返回值: 函数可以返回引用类型,以便调用者可以使用相同的名称访问函数返回的变量或对象。这也可以避免大型结构体或对象复制的开销,提高程序效率。

引用并不是值传递,而是通过地址传递。当我们将一个变量作为引用传递给函数时,函数得到的是该变量的地址,而不是变量的副本。因此,对引用所代表的变量进行的任何修改都会影响到原始变量。与之相反,当我们将变量作为值传递给函数时,函数得到的是该变量的一个副本,对副本的修改不会影响到原始变量

引用和指针的区别

引用和指针都可以用于间接访问变量或对象,但它们之间有以下几个区别:

  1. 语法: 引用使用&符号进行声明,而指针使用*符号进行声明。
  2. 空值: 指针可以为NULL或nullptr,表示指向空地址;而引用必须始终指向某个有效的对象。
  3. 初始化: 在声明时,引用必须被初始化为某个对象,而指针则可以在任何时候被初始化或赋值为一个地址。
  4. 可更改性: 一旦引用被初始化为某个对象,就不能再更改它的引用对象;而指针可以在任何时候重新分配到另一个对象。
  5. 所指对象的内存管理: 指针可以进行动态内存分配和释放,因此需要程序员手动管理内存;而引用只是对已经存在的对象的引用,无需手动管理内存。

需要注意的是,引用实际上是通过指针来实现的。当我们创建一个引用时,编译器会为该引用创建一个指针,并将其自动关联到所引用的变量。因此,从内部机制上说,引用和指针是密切相关的。

引用和指针都可以被视为值传递的方式,因为它们传递的是内存地址(即指向实际数据的指针),而不是数据本身。当使用引用或指针时,对该地址上的数据进行更改会影响原始数据。

#include<bits/stdc++.h>
using namespace std;int main() {int a;int& ra = a;a = 999;cout << typeid(&a).name() << endl;cout << typeid(&ra).name() << endl;cout << &a << endl;cout << &ra << endl;return 0;
}

C++ STL 教程

在前面的章节中,我们已经学习了 C++ 模板的概念。C++ STL(标准模板库)是一套功能强大的 C++ 模板类,提供了通用的模板类和函数,这些模板类和函数可以实现多种流行和常用的算法和数据结构,如向量、链表、队列、栈。

C++ 标准模板库的核心包括以下三个组件:

组件描述
容器(Containers)容器是用来管理某一类对象的集合。C++ 提供了各种不同类型的容器,比如 deque、list、vector、map 等。
算法(Algorithms)算法作用于容器。它们提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。
迭代器(iterators)迭代器用于遍历对象集合的元素。这些集合可能是容器,也可能是容器的子集。

这三个组件都带有丰富的预定义函数,帮助我们通过简单的方式处理复杂的任务。

下面的程序演示了向量容器(一个 C++ 标准的模板),它与数组十分相似,唯一不同的是,向量在需要扩展大小的时候,会自动处理它自己的存储需求:

实例

#include <iostream>
#include <vector>
using namespace std;int main()
{// 创建一个向量存储 intvector<int> vec; int i;// 显示 vec 的原始大小cout << "vector size = " << vec.size() << endl;// 推入 5 个值到向量中for(i = 0; i < 5; i++){vec.push_back(i);}// 显示 vec 扩展后的大小cout << "extended vector size = " << vec.size() << endl;// 访问向量中的 5 个值for(i = 0; i < 5; i++){cout << "value of vec [" << i << "] = " << vec[i] << endl;}// 使用迭代器 iterator 访问值vector<int>::iterator v = vec.begin();while( v != vec.end()) {cout << "value of v = " << *v << endl;v++;}return 0;
}

当上面的代码被编译和执行时,它会产生下列结果:

vector size = 0
extended vector size = 5
value of vec [0] = 0
value of vec [1] = 1
value of vec [2] = 2
value of vec [3] = 3
value of vec [4] = 4
value of v = 0
value of v = 1
value of v = 2
value of v = 3
value of v = 4

关于上面实例中所使用的各种函数,有几点要注意:

  • push_back( ) 成员函数在向量的末尾插入值,如果有必要会扩展向量的大小。
  • size( ) 函数显示向量的大小。
  • begin( ) 函数返回一个指向向量开头的迭代器。
  • end( ) 函数返回一个指向向量末尾的迭代器。

http://www.ppmy.cn/news/67263.html

相关文章

系统移植(2023-5-10)

1.进入linux内核源码目录下&#xff0c;打开Makefile文件&#xff0c;搜索vmlinux&#xff0c;找到cmd_link-vmlinux命令&#xff0c; 1179 cmd_link-vmlinux \ 1180 $(CONFIG_SHELL) $< "$(LD)" "…

MySQL-图形化界面工具 (上)

♥️作者&#xff1a;小刘在C站 ♥️个人主页&#xff1a;小刘主页 ♥️每天分享云计算网络运维课堂笔记&#xff0c;努力不一定有收获&#xff0c;但一定会有收获加油&#xff01;一起努力&#xff0c;共赴美好人生&#xff01; ♥️树高千尺&#xff0c;落叶归根人生不易&…

常见概率分布及图像

概率分布 文章目录 概率分布[toc]1 离散概率分布1.1 伯努利分布1.2 二项分布1.3 泊松分布 2 连续概率分布2.1 均匀分布2.2 指数分布2.3 正态分布2.4 卡方分布2.5 Student分布3.5 F分布 1 离散概率分布 1.1 伯努利分布 随机变量 X X X仅取两个值&#xff0c; X 0 , 1 X0,1 X0…

毕业答辩只答不辩道歉攻略❗

1.当老师提出问题你完全不会时:感谢老师的提问&#xff0c;对于老师您提的这个问题&#xff0c;确实是我没有考虑到的地方。对于该问题的研究我还并不是特别了解&#xff0c;感谢老师的指正让我意识到我在这一问题上的缺漏。接下来我会继续查阅相关期刊文献&#xff0c;对论文内…

第5课 弹性之城--创意卡--听我说

上一次&#xff0c;我们简单构建了一个穿越到弹性之城的故事&#xff0c;你都有想到哪些奇思妙想的创意呢&#xff1f; 今天&#xff0c;让我们把能想到的创意全都梳理一下&#xff0c;看看都有哪些有趣的玩意儿。 1. 弹性桌椅 2. 弹性讲台 3. 弹性课桌 4. 弹性公交车 5. 弹性书…

python深度学习 -- 训练的数据集中出现NaN值应该怎么办?Filling gaps in a numpy array

python&深度学习 – 训练的数据集中出现NaN值应该怎么办&#xff1f; 在深度学习的一些应用场景中&#xff0c;如海洋气象要素的预测、纠正等等。对于训练数据往往需要进行前处理&#xff0c;如处理缺测值、归一化等等。 特别是存在缺测值的情况&#xff0c;如果在深度学…

15 KVM虚拟机配置-体系架构相关配置

文章目录 15 KVM虚拟机配置-体系架构相关配置15.1 概述15.2 元素介绍15.3 AArch64架构配置示例15.4 x86_64架构配置示例 15 KVM虚拟机配置-体系架构相关配置 15.1 概述 XML中还有一部分体系架构相关的配置&#xff0c;这部分配置包括主板&#xff0c;CPU&#xff0c;一些与体…

洗地机哪个品牌好?好用的家用洗地机分享

洗地机采用高效吸力和清洗方式&#xff0c;可快速清除地面污渍和痕迹&#xff0c;让地面干净整洁&#xff0c;提高使用者的生活品质和舒适度。洗地机不仅清洁效果好&#xff0c;而且操作简单&#xff0c;大多采用一键启动和一键停止&#xff0c;方便快捷&#xff0c;节省时间和…