目录
1、Vector2D 默认构造、重载
#include <iostream>
#include <cmath>
class Vector2D {
private:
double x; // X坐标
double y; // Y坐标
public:
// 默认构造函数,将向量初始化为(0,0)
Vector2D() : x(0), y(0) {}
// 带有两个参数的构造函数,用于初始化向量的x和y坐标
Vector2D(double x, double y) : x(x), y(y) {}
// 计算向量的长度
double length() const {
return std::sqrt(x * x + y * y);
}
// 重载+运算符,用于向量的加法
Vector2D operator+(const Vector2D& other) const {
return Vector2D(x + other.x, y + other.y);
}
// 打印向量的坐标
void print() const {
std::cout << "(" << x << ", " << y << ")" << std::endl;
}
};
int main() {
Vector2D v1(3, 4);
Vector2D v2(1, 2);
Vector2D v3 = v1 + v2;
v3.print(); // 输出:(4, 6)
return 0;
}
2、char 深度理解
背景
char* outex()
{
char szP[32] = "helllo";
return szP;
} 我理解是 szP的栈空间应该是被释放了 那么 return的时候 是把内容复制到返回值了?然后再释放的?
您的理解是正确的,`szP` 在 `outex` 函数中是一个栈上的局部变量。当函数返回时,这块栈空间会被标记为可以重用,但是不会立即被清零或释放。然而,返回一个栈上局部变量的指针是危险的,因为这块内存随时都可能被其他函数调用或其他局部变量覆盖,导致不确定的行为。
当您执行以下代码:
```cpp
char* ptr = outex();
```
您得到的 `ptr` 实际上是指向一个已经不再保证其内容的内存区域。这块内存很快就可能被其他操作覆盖。
要修复这个问题,有以下几种常见方法:
1. **静态存储**:使变量静态,这样它的生命周期会持续到程序结束。
```cpp
char* outex() {
static char szP[32] = "hello";
return szP;
}
```
注意:这种方法使得每次调用 `outex` 都返回相同的内存地址,所以如果您修改这块内存的内容,将影响所有引用该地址的地方。
2. **动态内存分配**:使用 `new` (或 `malloc` 在 C 中)为字符串分配堆内存。
```cpp
char* outex() {
char* szP = new char[32];
strcpy(szP, "hello");
return szP;
}
```
如果使用这种方法,您必须确保在使用完返回的指针后使用 `delete[]` (或 `free` 在 C 中)来释放分配的内存,以避免内存泄漏。
3. **使用 C++ 标准库的字符串**:这是一个更现代和安全的方法。
```cpp
std::string outex() {
return "hello";
}
```
在大多数情况下,推荐使用第三种方法,因为它最简单、安全。
3、深度理解简单的类操作
#include <iostream>
class SimpleClass {
private:
int value;
public:
SimpleClass(int v) : value(v) {}
int getValue() const {
return value;
}
void setValue(int v) {
value = v;
}
};
int main() {
SimpleClass obj(5);
std::cout << "Initial value: " << obj.getValue() << std::endl;
obj.setValue(10);
std::cout << "Updated value: " << obj.getValue() << std::endl;
return 0;
}
这个程序首先定义了一个名为`SimpleClass`的类,然后在`main`函数中实例化并使用该类。下面是其深层次的工作原理:
1. **内存模型**:
当`SimpleClass obj(5);`这行代码执行时,编译器在栈上为`SimpleClass`对象分配内存。这意味着`obj`对象的生命周期限制在其声明的作用域内,一旦离开这个作用域(例如`main`函数结束时),对象就会被销毁。
2. **构造函数**:
`SimpleClass(int v) : value(v) {}`是一个带有一个整数参数的构造函数。在构造函数的初始化列表中,我们直接将成员变量`value`初始化为参数`v`的值。
3. **成员函数**:
`getValue`和`setValue`是访问器函数,它们允许我们访问和修改私有成员`value`。
4. **数据封装**:
通过将`value`设为`private`,我们确保了它不能直接从类外部访问或修改。这是面向对象编程的基本原则之一,称为封装。
5. **输入/输出流**:
`std::cout`是C++的一个输出流对象,它用于将文本发送到标准输出(通常是屏幕)。`<<`操作符被重载,以便可以与`std::cout`和其他类型的数据一起使用,从而提供连续的输出操作。
6. **返回值**:
`main`函数的返回值通常指示程序的退出状态。返回0通常表示程序成功完成。
编译和运行该程序会输出:
```
Initial value: 5
Updated value: 10
```
当你编译这段代码时,编译器会执行许多任务,包括但不限于:词法分析、语法分析、语义分析、优化和代码生成。然后链接器接手,解析库依赖关系,并生成可执行文件。