在C++中,当类的成员变量是指针类型时,对象的管理会变得复杂,因为指针所指向的资源通常位于堆上,需要开发者显式控制其生命周期。如果处理不当,很容易出现内存泄漏、重复释放或悬空指针等问题。下面介绍几种在类中合理使用指针成员的技巧。

遵循构造与析构配对原则
如果类中含有原始指针成员并且在构造函数中分配了资源,那么必须在析构函数中释放。这是最基础的规则,能有效防止内存泄漏。
#include <iostream>
class Buffer {
private:
int* data;
public:
Buffer(int size) {
data = new int[size]; // 构造时分配
}
~Buffer() {
delete[] data; // 析构时释放
}
};
int main() {
Buffer buf(10);
return 0;
}
实现深拷贝避免浅拷贝陷阱
编译器生成的默认拷贝构造函数和赋值运算符只做浅拷贝,多个对象会指向同一块内存。当其中一个对象析构后,其他对象的指针就变成了悬空指针。因此需要自定义深拷贝。
#include <cstring>
class MyString {
private:
char* str;
public:
MyString(const char* s) {
str = new char[strlen(s) + 1];
strcpy(str, s);
}
// 深拷贝构造函数
MyString(const MyString& other) {
str = new char[strlen(other.str) + 1];
strcpy(str, other.str);
}
// 深拷贝赋值运算符
MyString& operator=(const MyString& other) {
if (this != &other) {
delete[] str;
str = new char[strlen(other.str) + 1];
strcpy(str, other.str);
}
return *this;
}
~MyString() {
delete[] str;
}
};
优先使用智能指针管理资源
现代C++推荐用std::unique_ptr或std::shared_ptr替代原始指针成员,它们能自动释放资源,大幅降低出错概率。
#include <memory>
#include <vector>
class TreeNode {
public:
std::unique_ptr<TreeNode> left;
std::unique_ptr<TreeNode> right;
int value;
TreeNode(int v) : value(v) {}
};
int main() {
auto root = std::make_unique<TreeNode>(1);
root->left = std::make_unique<TreeNode>(2);
return 0;
}
使用移动语义提升性能
对于含有指针成员的类,可以实现移动构造和移动赋值,将资源所有权转移而不是复制,减少不必要的内存分配。
#include <utility>
class Holder {
private:
int* ptr;
public:
Holder(int* p) : ptr(p) {}
Holder(Holder&& other) noexcept : ptr(other.ptr) {
other.ptr = nullptr; // 转移后置空
}
Holder& operator=(Holder&& other) noexcept {
if (this != &other) {
delete ptr;
ptr = other.ptr;
other.ptr = nullptr;
}
return *this;
}
~Holder() { delete ptr; }
};
总结建议
在C++对象中使用指针成员时,应明确资源归属,优先采用智能指针;若必须使用原始指针,则需严格遵循三法则或五法则,保证拷贝、赋值与销毁行为正确。这样能让对象与指针的结合既灵活又安全。