如何基于std::make_from_tuple在堆上创建C++对象?
实现从元组创建堆对象并返回裸指针的C++函数
你可以基于C++17引入的std::apply来实现这个需求,它能帮你把元组的元素展开为构造函数的参数,同时支持完美转发,适配包括std::unique_ptr在内的各类需要移动语义的类型。
核心实现代码
#include <tuple> #include <utility> // 用于std::forward和std::apply template <typename T, typename Tuple> T* make_new_from_tuple(Tuple&& tuple) { return std::apply( [](auto&&... args) { return new T(std::forward<decltype(args)>(args)...); }, std::forward<Tuple>(tuple) ); }
基础用法示例
用你给出的struct A来演示:
#include <string> struct A { int i_; double d_; std::string s_; A(int i, double d, const std::string& s) : i_(i), d_(d), s_(s) {} }; int main() { auto aTuple = std::make_tuple(1, 1.5, std::string("Hello")); A* aPtr = make_new_from_tuple<A>(aTuple); // 使用对象... delete aPtr; // 记得手动释放内存 return 0; }
支持移动语义的复杂场景
当元组包含std::unique_ptr这类需要移动的对象时,该实现也能正确处理:
#include <memory> struct B { std::unique_ptr<int> p_; B(std::unique_ptr<int> p) : p_(std::move(p)) {} }; int main() { auto bTuple = std::make_tuple(std::make_unique<int>(42)); B* bPtr = make_new_from_tuple<B>(std::move(bTuple)); // 使用对象... delete bPtr; return 0; }
为什么这个方案更优
- 避免了先通过
std::make_unique创建智能指针再调用release()的冗余操作,直接裸指针构造更高效直观。 - 依赖
std::apply的完美转发特性,确保元组中元素的值类别(左值/右值)被正确传递给构造函数,适配各类构造场景。 - 与
std::make_from_tuple的C版本要求一致(C17及以上),无需额外依赖。
内容的提问来源于stack exchange,提问作者CashCow
相关产品推荐
相关产品推荐

