优先使用智能指针传递动态分配对象,std::unique_ptr通过std::move转移独占所有权,确保资源安全释放;std::shared_ptr通过引用计数实现共享所有权,适合多部分共享对象的场景;避免原始指针以防止内存泄漏和悬空指针。

在C++函数中传递动态分配的对象,核心考量在于如何清晰地管理对象的所有权和生命周期。简单来说,最佳实践是优先使用智能指针,特别是
std::unique_ptr
std::shared_ptr
要安全、高效地在C++函数中传递动态分配的对象,我们主要有以下几种策略,每种都对应着不同的所有权语义:
传递独占所有权(std::unique_ptr
std::unique_ptr
std::unique_ptr
std::move
unique_ptr
#include <memory>
#include <iostream>
class MyResource {
public:
MyResource(int id) : id_(id) { std::cout << "MyResource " << id_ << " created.\n"; }
~MyResource() { std::cout << "MyResource " << id_ << " destroyed.\n"; }
void use() const { std::cout << "Using MyResource " << id_ << ".\n"; }
private:
int id_;
};
// 函数接收独占所有权
void processUniqueResource(std::unique_ptr<MyResource> res) {
if (res) {
res->use();
}
// res 在这里超出作用域时会自动销毁其指向的对象
}
// 示例用法
// int main() {
// std::unique_ptr<MyResource> r1 = std::make_unique<MyResource>(1);
// processUniqueResource(std::move(r1)); // 所有权转移
// // r1 现在是空的,不能再访问
// // if (r1) { /* 这段代码不会执行 */ }
// return 0;
// }传递共享所有权(std::shared_ptr
std::shared_ptr
shared_ptr
std::shared_ptr
const std::shared_ptr<T>&
#include <memory>
#include <iostream>
class SharedResource {
public:
SharedResource(int id) : id_(id) { std::cout << "SharedResource " << id_ << " created.\n"; }
~SharedResource() { std::cout << "SharedResource " << id_ << " destroyed.\n"; }
void report() const { std::cout << "Reporting from SharedResource " << id_ << ".\n"; }
private:
int id_;
};
// 函数接收共享所有权
void processSharedResource(std::shared_ptr<SharedResource> res) {
if (res) {
res->report();
std::cout << " Inside processSharedResource, use_count: " << res.use_count() << "\n";
}
// res 离开作用域时,引用计数减一
}
// 函数仅观察 shared_ptr 本身,不影响所有权
void inspectSharedPtr(const std::shared_ptr<SharedResource>& resPtr) {
if (resPtr) {
std::cout << " Inspecting shared_ptr, use_count: " << resPtr.use_count() << "\n";
}
}
// 示例用法
// int main() {
// std::shared_ptr<SharedResource> s1 = std::make_shared<SharedResource>(10);
// std::cout << "Initial use_count: " << s1.use_count() << "\n"; // 1
// processSharedResource(s1); // 传递值,引用计数增加
// std::cout << "After processSharedResource, use_count: " << s1.use_count() << "\n"; // 1
// inspectSharedPtr(s1); // 传递常量引用,引用计数不变
// std::cout << "After inspectSharedPtr, use_count: " << s1.use_count() << "\n"; // 1
// {
// std::shared_ptr<SharedResource> s2 = s1; // 复制,引用计数增加
// std::cout << "Inside block, use_count: " << s1.use_count() << "\n"; // 2
// } // s2 销毁,引用计数减一
// std::cout << "After block, use_count: " << s1.use_count() << "\n"; // 1
// return 0;
// }传递非所有权(原始指针或引用) 有时候,一个函数仅仅需要访问动态分配的对象,而不需要参与其所有权管理。在这种情况下,你可以从智能指针中获取原始指针(
get()
*
// 函数仅使用对象,不关心所有权
void useResourceDirectly(MyResource* res) {
if (res) {
res->use();
}
}
void useResourceByRef(MyResource& res) {
res.use();
}
// 示例用法
// int main() {
// std::unique_ptr<MyResource> r2 = std::make_unique<MyResource>(2);
// useResourceDirectly(r2.get()); // 传递原始指针
// useResourceByRef(*r2); // 传递引用
// return 0;
// }说实话,在现代C++中,直接通过原始指针(
T*
T*
delete
delete
delete
delete
delete
unique_ptr
shared_ptr
所以,除非你明确知道对象的所有权由别处严格管理,并且你的函数只是一个临时的“观察者”,否则,尽量远离直接传递原始指针来管理动态对象。这不仅仅是编码规范的问题,更是为了代码的健壮性和可维护性。
立即学习“C++免费学习笔记(深入)”;
std::unique_ptr
std::unique_ptr
unique_ptr
当你把一个
std::unique_ptr
std::move
std::move
unique_ptr
unique_ptr
unique_ptr
这种机制完美地解决了原始指针的所有权模糊问题:谁接收了
unique_ptr
#include <memory>
#include <iostream>
class Gadget {
public:
Gadget(int id) : id_(id) { std::cout << "Gadget " << id_ << " created.\n"; }
~Gadget() { std::cout << "Gadget " << id_ << " destroyed.\n"; }
void operate() const { std::cout << "Operating Gadget " << id_ << ".\n"; }
private:
int id_;
};
// 接收独占所有权,处理后销毁
void processAndDispose(std::unique_ptr<Gadget> g) {
if (g) {
g->operate();
std::cout << " Gadget " << g->id_ << " processed.\n";
}
// g 在这里离开作用域,自动调用 ~Gadget()
}
// 仅仅观察 Gadget,不获取所有权
void inspectGadget(const Gadget& g) {
g.operate();
std::cout << " Gadget " << g.id_ << " inspected by reference.\n";
}
int main() {
std::unique_ptr<Gadget> myGadget = std::make_unique<Gadget>(101);
std::cout << "Main scope: myGadget created.\n";
// 传递原始指针或引用给不获取所有权的函数
inspectGadget(*myGadget);
// 转移所有权给 processAndDispose
processAndDispose(std::move(myGadget));
std::cout << "Main scope: After processAndDispose call.\n";
// 此时 myGadget 已经为空,访问会是未定义行为
if (!myGadget) {
std::cout << "Main scope: myGadget is now empty.\n";
}
// 如果想在函数内部修改 unique_ptr 本身(比如让它指向新的对象),
// 可以传递 unique_ptr 的引用,但这种情况不常见,且需要小心所有权管理
// void modifyUniquePtr(std::unique_ptr<Gadget>& ptr) {
// ptr = std::make_unique<Gadget>(202);
// }
// modifyUniquePtr(myGadget); // 此时 myGadget 又指向新对象了
return 0;
}通过这个例子,我们能清楚看到
std::move
myGadget
processAndDispose
g
myGadget
std::shared_ptr
std::shared_ptr
shared_ptr
shared_ptr
shared_ptr
shared_ptr
这种机制特别适合那些对象生命周期不确定,或者需要被多个不相关的模块共同持有和访问的场景,比如:
shared_ptr
shared_ptr
std::weak_ptr
在函数中传递`std::shared
以上就是C++如何在函数中传递动态分配对象的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号