You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在构造函数初始化阶段完成vector中智能指针对象的克隆并创建std::set容器?

解决方案:在初始化阶段完成std::set的构造

当然可以做到!你想要把克隆和std::set的构造逻辑都放到初始化阶段、摆脱构造函数里的循环,其实可以借助C标准库的迭代器和初始化列表特性来实现,下面两种方案分别适配不同的C版本:

方案一:C++11及以上兼容版本

我们可以用**lambda表达式配合std::transform**在成员初始化列表里生成一个临时的、包含克隆后指针的容器,直接用它来构造std::set。这样所有逻辑都在初始化阶段完成,构造函数体内完全不需要循环:

#include <memory>
#include <set>
#include <vector>
#include <algorithm> // 用于std::transform

class A {
public:
    typedef A self;
    A() = default;
    A(const self& another) = default;
    virtual ~A() = default;
    std::unique_ptr<A> clone() const {
        return std::make_unique<A>();
    }
};

class SetOfA {
public:
    SetOfA() = default;
    // 优化后的构造函数:逻辑全部在初始化列表中
    SetOfA(const std::vector<std::unique_ptr<A>>& data)
        : set_of_a([&]() {
            // 在lambda里完成克隆元素的生成
            std::vector<std::unique_ptr<A>> cloned_elements;
            cloned_elements.reserve(data.size()); // 预分配空间提升性能
            std::transform(
                data.begin(), data.end(),
                std::back_inserter(cloned_elements),
                [](const std::unique_ptr<A>& ptr) {
                    return ptr->clone(); // 调用克隆方法生成新指针
                }
            );
            return cloned_elements;
        }()) // 执行lambda,返回的临时vector用来构造set
    {}

private:
    std::set<std::unique_ptr<A>> set_of_a;
};

这里的核心是:lambda表达式会在初始化set_of_a时执行,生成一个包含所有克隆后指针的临时std::vector,然后std::set会直接用这个vector的迭代器完成构造,全程不需要在构造函数体内写循环。

方案二:C++20及以上更简洁版本

如果你可以使用C++20的范围库(Ranges),可以直接用std::ranges::transform_view来生成一个“视图”,不需要临时vector,直接把转换后的元素序列传给std::set的构造函数,代码会更简洁:

#include <memory>
#include <set>
#include <vector>
#include <ranges> // C++20范围库

class A {
public:
    typedef A self;
    A() = default;
    A(const self& another) = default;
    virtual ~A() = default;
    std::unique_ptr<A> clone() const {
        return std::make_unique<A>();
    }
};

class SetOfA {
public:
    SetOfA() = default;
    // C++20优化版本:直接用transform_view构造set
    SetOfA(const std::vector<std::unique_ptr<A>>& data)
        : set_of_a(
            std::ranges::transform_view(
                data,
                [](const std::unique_ptr<A>& ptr) {
                    return ptr->clone();
                }
            )
        )
    {}

private:
    std::set<std::unique_ptr<A>> set_of_a;
};

std::ranges::transform_view相当于一个“懒加载”的转换层,它不会提前生成所有克隆元素,而是在std::set构造时按需生成并插入,既避免了临时容器的开销,又完全满足你在初始化阶段完成逻辑的需求。

补充说明

  • 两种方案都利用了std::set的范围构造函数,该函数可以接受任意输入迭代器序列来初始化集合。
  • std::unique_ptr是不可复制的,但clone()返回的是右值(临时对象),可以被正确移动到std::set中,没有所有权问题。

内容的提问来源于stack exchange,提问作者one_two_three

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 15:12:37