1.关于#include<iostream>
C++语言里#include<iostream>用于引入标准输入输出流[1]即cin(输入)和cout(输出),例如:
#include"iostream"
using namespace std;
int main(){
int j; //声明整数j
cin << j; //从键盘输入一个整数作为j的值
int i=1; //声明整数i的值为1
cout << "输出的内容" << i << endl; //输出i的值
}
而std::cout与cout的区别是:
std是一个命名空间(namespace),::是作用域运算符,cout是std空间中的一个函数名,所以使用cout时,必须有使用std命名空间的说明[2],有两种说明方式(cin同理),如下:
①方式一:每次使用时都对cout说明
#include"iostream"
int main(){
std::cout<<"Input two numbers:";
}
②方式二:在主函数前说明一下,后面就可以直接使用cout
#include"iostream"
using namespace std;
int main(){
cout << "Input two numbers:";
}
2.关于#pragma once
C++语言里#pragma once是用于预编译,为了避免 同一个头文件被include多次,这里所说的同一个文件是指物理上的一个文件,而不是指内容相同的两个文件
3.关于#include<cstdlib>
C++语言里#include<cstdlib>相当于C语言中#include<stdlib.h>的增强版,它包含了C标准库的通用工具函数,如malloc和free函数等
4. nullptr关键字
①在C++11之前,通常使用0或NULL来表示指针为空;在C++11中,引入了nullptr关键字,它被定义为std::nullptr_t数据类型的字面值常量,用于表示空指针
②C++11中,初始化指针变量时,可以将其初始化为nullptr,如:int *p = nullptr,这种方式可以避免由于误解空指针的含义而导致的错误
③在C++11之后,不推荐使用0或NULL来表示空指针,因为它们在语义上不够明确,容易产生歧义;此外,对于整型变量和指针类型变量 混用时,可能会导致一些问题
④由于nullptr是一个关键字,在进行初始化时不能将其改成其他字符,否则将会导致编译错误
5. new关键字
①new是C++语言中的一个关键字,用于在堆区 动态分配内存并返回其地址(即指针),可以使用new关键字实例化一个类对象、*分配一个数组或在堆区中动态分配内存等
②对于基本数据类型,使用new时可以指定初值,例如:
int *p = new int(10); //分配4个字节的内存,初始化为10,返回指向该内存的指针
③对于自定义类型,需要通过构造函数来初始化对象,例如:
class MyClass {
public:
MyClass() { cout << "MyClass Constructor" << endl; }
};
MyClass *obj = new MyClass(); //动态分配内存并调用构造函数,返回指向该对象的指针
④需要注意的是,在使用new关键字动态分配内存时,如果程序出现异常终止,可能会导致内存泄漏,所以在动态分配内存后应必须手动使用delete关键字释放内存,或使用智能指针等方式来自动管理内存
6.指向常量对象的常量指针(如:const double *point)
#include "iostream"
using namespace std;
int main() {
const double pi = 3.14;
const double *point = π //指向常量对象的常量指针
//不能通过指针point来修改pi的值
cout << "pi的原始值:" << pi << endl; //输出为 pi的原始值:3.14
//*point = 3.1415; //错误:指针point指向的对象是常量,不能修改其值
//但是指针point自身的值可以修改,即可以指向其他的常量对象
const double anotherPi = 3.1415926;
point = &anotherPi; //可以修改指针point指向的其他对象的地址
cout << "anotherPi的值:" << *point << endl; //输出为 anotherPi的值:3.14159
return 0;
}
7.指向常量的常量指针(如:double* const point)
#include "iostream"
using namespace std;
int main() {
double a = 1.0, b = 2.0;
double* const point = &a; //指向常量的常量指针
//指针point指向的对象是变量,可以通过指针point来修改该对象的值
cout << "a的原始值:" << a << endl; //输出为 a的原始值:1
*point = 3.0;
cout << "a改变后的值:" << a << endl; //输出为 a的改变后的值:3
//但是指针point自身的值不能修改,即不能指向其他的对象
//point = &b; //错误:指针point是常量,其地址不能改变
return 0;
}
8.内联函数
①内联函数是一种特殊的函数,它的函数体通常比较短小,并被频繁使用;在编译时,编译器将在每个调用处直接把内联函数的代码嵌入到调用该函数的地方,这样可以减少函数调用的开销,提高程序的执行效率
②内联函数是对函数调用机制的优化,它并不影响函数的本质,且仍然遵循函数的语法
③内联函数的局限性:内联函数过多会导致可执行程序的体积增大
④内联函数不能被递归调用,因为递归需要在函数栈中存储每次调用的数据和返回地址,而内联函数的代码是在调用点直接嵌入到程序中的,没有函数栈
⑤在C++语言中,用关键字inline来声明一个内联函数,如下:
#include "iostream"
using namespace std;
//声明内联函数add
inline int add(int a, int b) {
return a + b;
}
int main() {
int a = 3, b = 4;
int sum = add(a, b); // 调用内联函数add
cout << "sum = " << sum << endl;
return 0;
}
9.构造函数与内联函数
①构造函数的调用时机和普通函数不同,构造函数在对象被创建时被调用,而不是通过函数名进行显式调用
②构造函数可以被声明为内联函数,因为它们经常被用来创建类的对象,并且它们的函数体通常比较短小
③将构造函数声明为内联函数并不是必须的,只有当构造函数的函数体非常简短并且在程序中被频繁使用时才可以考虑使用内联函数,如果构造函数的函数体很长,则声明为内联函数会增加可执行文件的大小而会适得其反,不过由于编译器会根据具体情况决定是否将函数展开成内联函数,所以在实际上,将构造函数声明为内联函数可能并不能真正地提高程序的执行效率
10.析构函数(析构方法)
#include "iostream"
#include "cstring"
class Person {
public:
// 构造函数
Person(const char* name, int age) {
m_name = new char[strlen(name) + 1];
strcpy(m_name, name);
m_age = age;
}
// 析构函数
~Person() {
std::cout << "释放 " << m_name << " 所占用的内存" << std::endl;
delete[] m_name;
}
// 成员函数
void printInfo() {
std::cout << "姓名:" << m_name << ", 年龄:" << m_age << std::endl;
}
private:
char* m_name;
int m_age;
};
int main() {
// 创建一个 Person 对象
Person* person = new Person("Jack", 25);
// 使用对象的成员函数
person->printInfo();
// 释放对象所占用的内存
delete person;
return 0;
}
①析构函数(析构方法)写法为~类名() {}
②析构函数是一种特殊的成员函数,当一个对象被销毁时,如:一个局部变量离开了作用域、一个对象被delete掉等,就会执行析构函数
③析构函数通常用于释放对象所占用的资源,如:释放动态分配的内存、关闭打开的文件、断开网络连接等,但由于C++语言没有垃圾回收机制,因此需要手动释放资源,否则可能会导致程序崩溃或资源泄漏等问题