赞
踩
cin
, cin.get()
, getchar()
, getline()
, 和 cin.getline()
的区别。cin
通常用于读取单个单词或基本类型数据,遇到空白字符会停止。cin.get()
和getchar()
用于读取单个字符,包括空白字符,但getchar()
不是cin
的成员函数。getline()
和cin.getline()
用于读取整行数据,包括空白字符,直到换行符。getline()
可以读取到string
对象中,而cin.getline()
需要指定字符数组缓冲区。cin.getline()
会从输入流中取出分隔符,而getline()
则不会。cin
和cin.get()
在读取失败时,可能会设置错误标志,而getchar()
不会影响cin
的错误状态。#include <iostream> #include <string> int main() { // 使用 cin 读取一个单词 // 当你输入一个单词并按回车时,cin只会读取直到第一个空白字符之前的文本,所以如果输入Hello World,只会输出Hello。 std::string word; std::cout << "Enter a word: "; std::cin >> word; std::cout << "You entered: " << word << std::endl; // 清除输入缓冲区中的剩余字符(包括换行符) std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 使用 cin.get() 读取一个字符 // cin.get()会读取输入流中的下一个字符,即使它是空白字符。如果在上一个例子中直接按回车,它会读取换行符。 char ch; std::cout << "Enter a character: "; ch = std::cin.get(); std::cout << "You entered: " << ch << std::endl; // 使用 getchar() 读取一个字符 // getchar()与cin.get()类似,但它是从标准输入读取字符,不会影响cin的状态。 std::cout << "Enter another character: "; ch = getchar(); std::cout << "You entered: " << ch << std::endl; // 清除输入缓冲区中的剩余字符(包括换行符) std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // 使用 getline() 读取整行 // getline()读取整行,包括空白字符,直到遇到换行符。如果你输入This is a line,它会输出整行。 std::string line; std::cout << "Enter a line of text: "; getline(std::cin, line); std::cout << "You entered: " << line << std::endl; // 使用 cin.getline() 读取整行 // cin.getline()读取整行,包括空白字符,但它需要指定一个字符数组来存储输入的字符串 char buffer[256]; std::cout << "Enter another line of text: "; std::cin.getline(buffer, sizeof(buffer)); std::cout << "You entered: " << buffer << std::endl; return 0; }
// cin >> 的函数原型:
std::istream& operator>>(std::istream& in, int& value);
cin >>
实际上调用cin
的成员函数operator>>(int& value)
,cin
是 std::istream
类型的对象
// 链式调用的原理:返回类型为std::istream&
cin >> n >> m >> k;
// 实际上是:
cin >> n;
cin >> m;
cin >> k;
声明(Declaration):
extern
关键字来指定变量或函数在其他地方定义。定义(Definition):
extern int var; // 声明一个变量
void function(int param); // 声明一个函数
int globalVar = 10; // 定义一个全局变量,并初始化
void function(int param) {
// 定义一个函数
// 函数体
}
// question int x; 是个定义还是声明?
// 有extern是声明,没有extern是声明及定义
union
、struct
和class
的区别union
、struct
和class
都用于自定义数据类型 ,union
不可拥有静态成员及虚函数且不可继承,struct
和class
的主要区别在于默认的访问权限。
Union
union
可以存储不同的数据类型,但在同一时刻只能存储其中一个类型的值。Struct
struct
(结构体)是一种用于封装不同数据类型的数据项的集合。struct
的成员是公有的(public)。struct
通常用于简单的数据聚合,不涉及复杂的操作或继承。Class
class
是C++面向对象编程的核心,用于定义对象和它们的操作。class
的成员是私有的(private)。class
支持继承、多态、封装和抽象等面向对象的概念。浅拷贝在资源管理及数据独立性上有很大问题!会出现未定义行为
浅拷贝就是将对象的指针进行简单的复制,原对象和副本指向的是相同的资源。
深拷贝新开辟一块空间,将原对象的资源复制到新的空间中,并返回该空间的地址。
深拷贝可以避免重复释放和写冲突。例如使用浅拷贝的对象进行释放后,对 原对象的释放会导致内存泄漏或程序崩溃。
在C++中,如果不显式定义拷贝构造函数和赋值运算符,编译器会为类自动生成默认的浅拷贝版本。
// 深拷贝 class MyString { public: // 构造函数 MyString(const char* str = nullptr) { if (str) { size_ = strlen(str); data_ = new char[size_ + 1]; strcpy(data_, str); } else { size_ = 0; data_ = new char[1]; *data_ = '\0'; } } // 拷贝构造函数(深拷贝) MyString(const MyString& other) { size_ = other.size_; data_ = new char[size_ + 1]; strcpy(data_, other.data_); } // 拷贝赋值运算符重载(深拷贝) MyString& operator=(const MyString& other) { if (this != &other) { delete[] data_; size_ = other.size_; data_ = new char[size_ + 1]; strcpy(data_, other.data_); } return *this; } // 析构函数 ~MyString() { delete[] data_; } private: char* data_; size_t size_; };
new/delete |
malloc/free |
|
---|---|---|
属性 | 运算符重载 | 库函数 |
参数 | 无须指定内存块的大小,编译器会根据类型信息自行计算 | 要显式地指出所需内存的大小 |
返回值 | 返回对象类型的指针 | 返回 void * ,需要强转 |
自定义? | 可以做自定义类型对象的构造/析构函数 | 无法做自定义类型对象构造/析构工作 |
重载? | 允许重载 | 没有重载机制 |
异常处理 | 抛出std::bad_alloc 异常 |
失败为 NULL |
// question:有了malloc/free,C++中为什么还需要new/delete?
// 对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数,malloc/free无法满足
// 实际上,new/detele 是封装malloc/free 实现的
class Example {
......
static void* operator new(std::size_t size) {
// 调用malloc 分配内存
// 调用构造函数
// 返回指针
}
}
并不是,返回给堆
C++的调用惯例是编译器在执行函数调用时的规则,它定义了参数传递的方式、返回值的处理、寄存器的使用等。参数从右到左依次压入堆栈,函数调用者负责清理堆栈。
delete
和delete []
都是用于释放动态分配内存的运算符,但它们之间存在一些关键的区别。当delete []
操作符用于数组时, 它为每个数组元素调用析构函数,然后调用 operator delete 来释放内存。
释放对象 or 数组:
delete
用于释放单个对象所占用的内存。delete []
用于释放数组对象所占用的内存。内存释放方式:
delete
释放单个对象时,会调用对象的析构函数。delete []
释放数组对象时,会调用数组对象的析构函数,并且会自动调用数组中每个元素的析构函数。class Test { public: Test() { cout << "构造啦" << endl; } ~Test() { cout << "析构啦" << endl; } }; int main() { Test* array = new Test[4]; delete[] array; return 0; } // output 构造啦 构造啦 构造啦 构造啦 析构啦 析构啦 析构啦 析构啦
数组内存释放:
delete
不适用于数组,如果尝试使用delete
释放数组,只会调用一次析构函数。delete []
用于释放数组时,会释放整个数组所占用的内存,包括数组中的每个元素。class Test { public: Test() { cout << "构造啦" << endl; } ~Test() { cout << "析构啦" << endl; } }; int main() { Test* array = new Test[4]; delete array; return 0; } // output 构造啦 构造啦 构造啦 构造啦 析构啦
构造顺序:父类的构造函数->子类的构造函数
析构顺序:子类的析构函数->父类的析构函数
当一个派生类对象被销毁时,首先会调用派生类的析构函数,然后自动调用基类的析构函数(无论析构函数是否是虚函数)。这样可以确保基类和派生类的资源都能被正确地释放。
class Test {
public:
Test() {
cout <<
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。