The Leak of The Memory In C++ 1.1

本文介绍如何通过C++智能指针避免直接使用原始指针,阐述了智能指针的概念、封装和作用,包括auto_ptr的使用方法及其限制。文中详细解释了智能指针如何帮助开发者在不考虑性能损失的情况下,安全地管理内存,同时提醒开发者注意其特定的副作用,如不能赋值给另一个auto_ptr实例和不能放入容器中。
    Recent days I want to write some articles to summarise the knowledge
of C++ for practicing my English. So...

The Leak of The Memory in C++ (chapter 1.1)


    So many people asked me something about the leak of the memory. They
said that in C++ you must be careful when use pointer. I must say they were
right before STL published.
    In C++, we have so many methods to avoid to using pointer, why people
always convince developers to use pointer. In this article, I'll try to convince
regular developers to give raw pointer up and to forget it in your development.
    First, I want to show you the easest way to avoid using pointer which
is smart pointer in STL (if you don't know what is STL, I recommand you read a
book which name is "C++ Primer").
    In C++, smart pointer is a way to convince people to give raw pointer
up. smart pointer is a C++ class which encapsulates a raw pointer and which
can release the raw pointer when pointer leaves its scope. In C++98, which
provides just one smart pointer for developer, But so many people provide so
many another kinds of smart pointer in boost, Loki etc.
    Before I introduce the way to use smart pointers, I'll introduce a
class to you, even this class alread introduced in lots of books, and I will
use this class in demos.

    the source code in Person.h

#ifndef __PERSON__H
#define __PERSON__H

#include <string>

using namespace std;

class Person
{
    int age_;
    string name_;

public:
    Person()
        : age_(0)
    {}

    ~Person()
    {
        cout << "I'm destructed" << endl;
    };

public:
    int getAge()
    {
        return age_;
    }

    void setAge(int age)
    {
        age_ = age;
    }

    const string& getName()const
    {
        return name_;
    }

    void setName(const string& name)
    {
        name_ = name;
    }
};
#endif//__PERSON__H



    The auto_ptr, the first smart pointer I'll introduce to you. As a
first smart pointer appeared in STL, it is a miracle for me, because this one
I found a way to avoid using raw pointer, I found that what is Encapsulation
and what is Templement. The code is below:

#include <iostream>
#include <memory>
#include "Person.h"

using namespace std;

int main(int, char**)
{
    auto_ptr<Person> p1(new Person);
    auto_ptr<Person> p2(new Person);
    auto_ptr<Person> p3(new Person);
    return 0;
}


    If you execute code, you will find that every object's destructors are
called, so you can use auto_ptr in your functions, classes without consideration
of loss of performence.
    You already know benifit of the auto_ptr, but you must be careful its side effect.
    1. you can't assign an auto_ptr to another anto_ptr, if you did, just
like this:
    auto_ptr<Person> p1(new Person);
    auto_ptr<Person> p2 = p1;
    you would find that p1 is empty now.
    2. you can't put an auto_ptr in vector or another containers, I
think I have unnecessary to warry about this, because compiler will prevent you do
that.

<think> 我们正在从C语言转向C++,需要了解C++相对于C的主要新增特性和编程范式变化。下面将详细介绍C++的核心特性、与C的区别、以及如何逐步迁移代码。 注意:C++几乎是C的超集,但并非完全兼容(例如,C++中变量声明位置更灵活,类型检查更严格等)。 1. 面向对象编程(OOP) C++支持类、继承、多态等OOP特性。 2. 模板(泛型编程) 3. 异常处理 4. 标准模板库(STL) 5. 引用 6. 命名空间 7. 函数重载 8. 自动内存管理(智能指针等,但手动管理仍可用) 下面我们将通过对比C和C++的代码来展示这些特性。 ### 1. 基础语法差异 #### 输出 C语言使用`printf`,C++使用`cout`(需要包含`<iostream>`) **C语言示例:** ```c #include <stdio.h> int main() { printf("Hello, C!\n"); return 0; } ``` **C++示例:** ```cpp #include <iostream> using namespace std; int main() { cout << "Hello, C++!" << endl; return 0; } ``` 解释: - `using namespace std;` 引入标准命名空间,避免每次写`std::cout` - `cout`和`cin`分别用于输出和输入 - `endl`用于换行并刷新输出缓冲区 ### 2. 函数重载 C++允许同名函数根据参数不同而存在多个版本,C语言不允许。 ```cpp #include <iostream> using namespace std; // 两个整数的加法 int add(int a, int b) { return a + b; } // 两个浮点数的加法 double add(double a, double b) { return a + b; } int main() { cout << add(1, 2) << endl; // 调用int版本 cout << add(1.1, 2.2) << endl; // 调用double版本 return 0; } ``` ### 3. 引用(Reference) 引用是变量的别名,必须在定义时初始化,且不能改变指向。 ```cpp #include <iostream> using namespace std; int main() { int a = 10; int &ref = a; // ref是a的引用 ref = 20; // 修改ref相当于修改a cout << a << endl; // 输出20 return 0; } ``` 引用常用于函数参数传递(避免拷贝,且比指针更安全): ```cpp void swap(int &a, int &b) { int temp = a; a = b; b = temp; } ``` ### 4. 面向对象编程 #### 类定义 ```cpp #include <iostream> #include <string> using namespace std; // 定义一个Person类 class Person { private: // 私有成员 string name; int age; public: // 公有成员 // 构造函数 Person(string n, int a) : name(n), age(a) {} // 成员函数 void display() { cout << "Name: " << name << ", Age: " << age << endl; } // 设置年龄 void setAge(int a) { if (a > 0) age = a; } }; int main() { Person p("Alice", 30); p.display(); // 输出:Name: Alice, Age: 30 p.setAge(31); p.display(); // 输出:Name: Alice, Age: 31 return 0; } ``` #### 继承 ```cpp // 派生类Student class Student : public Person { private: string studentId; public: Student(string n, int a, string id) : Person(n, a), studentId(id) {} void display() { // 覆盖基类方法 Person::display(); // 调用基类方法 cout << "Student ID: " << studentId << endl; } }; int main() { Student s("Bob", 20, "S12345"); s.display(); // 输出基类和派生类信息 return 0; } ``` ### 5. 模板(泛型编程) 模板允许编写与类型无关的代码。 ```cpp // 函数模板 template <typename T> T max(T a, T b) { return (a > b) ? a : b; } int main() { cout << max(1, 2) << endl; // T为int cout << max(1.5, 2.3) << endl; // T为double return 0; } ``` ### 6. 标准模板库(STL) STL提供容器、迭代器、算法等。 #### vector容器示例 ```cpp #include <vector> #include <algorithm> // 排序算法 int main() { vector<int> nums = {3, 1, 4, 1, 5, 9}; // 排序 sort(nums.begin(), nums.end()); // 遍历 for (int num : nums) { cout << num << " "; } // 输出:1 1 3 4 5 9 return 0; } ``` ### 7. 异常处理 ```cpp #include <stdexcept> double divide(double a, double b) { if (b == 0) { throw invalid_argument("除数不能为零"); } return a / b; } int main() { try { cout << divide(10, 2) << endl; cout << divide(10, 0) << endl; } catch (const invalid_argument& e) { cerr << "错误: " << e.what() << endl; } return 0; } ``` ### 8. 智能指针(自动内存管理) 避免内存泄漏,包括`unique_ptr`, `shared_ptr`, `weak_ptr`。 ```cpp #include <memory> int main() { // 独占指针 unique_ptr<int> p1(new int(10)); // auto p1 = make_unique<int>(10); // C++14后推荐写法 // 共享指针 shared_ptr<int> p2 = make_shared<int>(20); auto p3 = p2; // 共享所有权 // 当指针离开作用域时自动释放内存 return 0; } ``` ### 迁移步骤建议 1. 将文件扩展名从`.c`改为`.cpp` 2. 使用C++标准头文件(如`<iostream>`代替`<stdio.h>`,使用`<cstdio>`代替`<stdio.h>`) 3. 逐步将函数改为C++风格(如使用引用参数代替指针) 4. 用`new/delete`替换`malloc/free` 5. 使用命名空间 6. 利用STL容器替代手动数据结构 7. 使用异常处理错误 8. 考虑使用类封装数据和函数 ### 注意事项 - **兼容性问题**:C++比C类型检查更严格,例如在C++中`void*`不能隐式转换为其他指针类型,需要显式转换。 - **常用技巧**:在C++中使用`extern "C"`来声明C函数,以兼容C代码。 ### 总结 C++提供了更强大的抽象机制和更安全的编程方式,但同时也增加了复杂性。从C迁移到C++需要理解面向对象、模板、STL等概念。 §§相关问题§§: 1. C++中的引用和指针有何本质区别? 2. 如何理解C++的多态性?请举例说明。 3. 在哪些场景下应该使用智能指针而不是原始指针? 4. STL中的vector和list在性能上有何不同? </think> ### C语言转C++学习指南 下面是核心语法差异、迁移路径和现代C++特性的系统整理,包含实用代码示例: #### 一、基础语法迁移 ```cpp // --------------- C vs C++ 对比示例 --------------- // C语言 (文件扩展名.c) #include <stdio.h> #include <stdlib.h> struct Point { int x; int y; }; void print_point(struct Point p) { printf("(%d, %d)\n", p.x, p.y); } int main() { struct Point p1 = {3, 4}; print_point(p1); int* arr = (int*)malloc(5 * sizeof(int)); free(arr); return 0; } // C++ (文件扩展名.cpp) #include <iostream> using namespace std; // 类替代struct(默认成员公有) class Point { public: int x; int y; // 成员函数 void print() { cout << "(" << x << ", " << y << ")\n"; } }; int main() { Point p1{3, 4}; // 统一初始化语法 p1.print(); // 直接调用成员函数 // 智能指针替代malloc/free auto arr = make_unique<int[]>(5); // 引用类型 int a = 10; int& ref = a; // ref是a的别名 ref = 20; // 修改原变量 return 0; } ``` #### 二、面向对象核心概念 ```cpp // ----------------- 类与对象 ----------------- class BankAccount { private: string owner; double balance; public: // 构造函数 BankAccount(string name, double init) : owner(name), balance(init) {} // 成员函数 void deposit(double amount) { balance += amount; } // 常量成员函数 double getBalance() const { return balance; } // 静态成员 static double interestRate; }; // ----------------- 继承与多态 ----------------- class SavingsAccount : public BankAccount { public: SavingsAccount(string name, double init) : BankAccount(name, init) {} // 重写基类方法 void deposit(double amount) override { BankAccount::deposit(amount * 1.05); // 增加5%奖励 } }; // 使用示例 int main() { SavingsAccount acc("Alice", 1000); acc.deposit(500); // 实际存入525 // 多态示例 BankAccount* base = &acc; base->deposit(100); // 动态调用SavingsAccount版本 } ``` #### 三、现代C++核心特性 ```cpp // ----------------- 智能指针 ----------------- #include <memory> void manageMemory() { // 独占所有权 auto uPtr = make_unique<int>(10); // 共享所有权 auto sPtr = make_shared<vector<int>>(); sPtr->push_back(42); } // ----------------- 模板编程 ----------------- template <typename T> T max(T a, T b) { return (a > b) ? a : b; } // 使用 auto m = max(3.5, 2.7); // 自动推导为double // ----------------- Lambda表达式 ----------------- auto multiply = [](auto a, auto b) { return a * b; }; cout << multiply(4, 5.5); // 输出22 // ----------------- STL容器使用 ----------------- #include <vector> #include <unordered_map> void useContainers() { vector<int> nums{1, 2, 3}; nums.push_back(4); unordered_map<string, int> ages{{"Alice", 30}, {"Bob", 25}}; cout << ages["Alice"]; // 输出30 } ``` #### 四、迁移最佳实践路径 1. **基础迁移步骤** - 文件扩展名:`.c` → `.cpp` - 头文件:`stdio.h` → `cstdio` - 内存管理:`malloc/free` → `new/delete` → `智能指针` - 输出:`printf` → `cout` + `<<` 运算符 2. **中级重构** ```cpp // 过程式 → 面向对象 // C风格 struct Data d; process_data(&d); // C++风格 class DataProcessor { public: void process(); private: Data internalData; }; ``` 3. **高级现代化** - 异常处理替代错误码 - 模板替代宏定义 - Range-based循环替代传统for - Lambda替代函数指针 #### 五、必备工具链 | 工具 | 用途 | 示例命令 | |------|------|----------| | GDB | 调试器 | `gdb ./program` | | Valgrind | 内存检测 | `valgrind --leak-check=yes ./program` | | CMake | 构建系统 | `cmake_minimum_required(VERSION 3.10)` | | Clang-Tidy | 代码检查 | `clang-tidy -checks=modernize-* source.cpp` | #### 六、学习资源推荐 1. 书籍:《C++ Primer》《Effective Modern C++》 2. 在线:LearnCPP.com、CppReference.com 3. 编译器:GCC(G++)、Clang、MSVC 4. IDE:Visual Studio、CLion、VS Code + C++插件
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值