C++使用make_unique把一个对象复制到另一个对象
·
在 C++ 中,std::make_unique用于动态分配对象并返回一个std::unique_ptr,但它本身不直接支持复制构造对象,因为make_unique会创建一个新的独立对象。如果你需要将一个已有对象复制到另一个unique_ptr管理的对象中,通常需要以下步骤:
1.直接复制对象(不推荐)
如果目标对象是可拷贝构造的,你可以先复制对象,再用make_unique管理它:
#include <memory>
#include <iostream>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
MyClass(const MyClass& other) : value(other.value) { // 拷贝构造函数
std::cout << "Copy constructed" << std::endl;
}
};
int main() {
MyClass obj1(42);
// 方法1:显式拷贝构造,再用 make_unique 管理
auto obj2_ptr = std::make_unique<MyClass>(obj1); // 调用拷贝构造函数
std::cout << obj2_ptr->value << std::endl; // 输出: 42
return 0;
}
缺点:
• 需要显式调用拷贝构造函数,可能不够直观。
• 如果MyClass的拷贝构造函数是私有的或删除的,此方法会失败。
2.通过unique_ptr的reset或直接构造
如果源对象本身由unique_ptr管理,可以通过reset或直接构造新指针:
#include <memory>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
MyClass(const MyClass& other) : value(other.value) {}
};
int main() {
auto src_ptr = std::make_unique<MyClass>(42);
// 方法2:通过 reset 或直接构造
auto dest_ptr = std::make_unique<MyClass>(*src_ptr); // 调用拷贝构造函数
std::cout << dest_ptr->value << std::endl; // 输出: 42
return 0;
}
3.使用std::unique_ptr的移动语义(不复制)
如果不需要复制,而是转移所有权,可以直接用std::move:
auto src_ptr = std::make_unique<MyClass>(42);
auto dest_ptr = std::move(src_ptr); // 转移所有权,src_ptr 变为 nullptr
if (!src_ptr) {
std::cout << "src_ptr is now empty" << std::endl;
}
std::cout << dest_ptr->value << std::endl; // 输出: 42
4.自定义克隆函数(推荐)
如果需要动态复制unique_ptr管理的对象,可以定义一个克隆函数(如clone()),返回新的unique_ptr:
#include <memory>
class MyClass {
public:
int value;
MyClass(int v) : value(v) {}
MyClass(const MyClass& other) : value(other.value) {}
// 定义克隆函数
std::unique_ptr<MyClass> clone() const {
return std::make_unique<MyClass>(*this);
}
};
int main() {
auto src_ptr = std::make_unique<MyClass>(42);
// 方法4:通过克隆函数复制
auto dest_ptr = src_ptr->clone();
std::cout << dest_ptr->value << std::endl; // 输出: 42
return 0;
}
优点:
• 代码清晰,直接表达“复制”语义。
• 适用于复杂对象或需要深拷贝的场景。
总结
| 方法 | 适用场景 | 是否调用拷贝构造函数 |
|---|---|---|
| make_unique(obj) | 从已有对象构造新 unique_ptr | ✅ 是 |
| reset 或直接构造 | 从另一个 unique_ptr 复制 | ✅ 是 |
| std::move | 转移所有权(不复制) | ❌ 否(原指针变为空) |
| 自定义 clone() 函数 | 需要灵活控制复制逻辑 | ✅ 是 |
注意事项
1.性能:拷贝构造可能触发深拷贝(如对象持有动态资源),需确保拷贝构造函数正确实现。
2.异常安全:make_unique是异常安全的,但直接拷贝构造需确保源对象有效。
3.多态支持:如果基类指针指向派生类对象,需通过虚函数实现多态克隆(见下文扩展)。
扩展:多态对象的克隆
如果涉及继承,可以通过基类虚函数实现多态克隆:
class Base {
public:
virtual ~Base() = default;
virtual std::unique_ptr<Base> clone() const = 0;
};
class Derived : public Base {
public:
int value;
Derived(int v) : value(v) {}
std::unique_ptr<Base> clone() const override {
return std::make_unique<Derived>(*this);
}
};
int main() {
std::unique_ptr<Base> src = std::make_unique<Derived>(42);
auto dest = src->clone(); // 多态克隆
return 0;
}
这样,无论src指向哪种派生类,clone()都能正确复制对象。
更多推荐

所有评论(0)