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

类转换直接初始化消除中间对象的规则?与工厂函数、Wrapper的差异

关于std::tuple与自定义Wrapper中对象初始化优化的疑问

背景

我在寻找std::tuple原地初始化的方法时,发现了一个依赖类间转换的已发布解决方案。为了理解是什么规则导致中间对象被消除,我构建了以下最小示例:

#include <cstdio>
#include <tuple>

class To {
   public:
    To() { std::puts("default constructor"); }
    explicit To(int input) : val(input) { std::puts("value constructor"); }
    // noexcept is a sweet lie because of std::puts
    To(To&& object) noexcept : val(object.val) {
        std::puts("move constructor");
    }
    // noexcept is a sweet lie because of std::puts
    To& operator=(To&& object) noexcept {
        val = object.val;
        std::puts("move assign");
        return *this;
    }
    ~To() noexcept { std::puts("destructor"); }

   private:
    int val = -1;
};

class From {
   public:
    explicit From(int input) : val(input) {
        std::puts("From value constructor");
    }
    // marking explicit to inhibit to1 assignement
    operator To() const&& { return To{val}; };

   private:
    int val = -1;
};

To Make_To(int val) { return To{val}; }

int main() {
    std::puts("-----------------");
    std::puts("# direct init with conversion");
    const std::tuple<To> tp0{From{0}};
    std::puts("# direct init with creator");
    const std::tuple<To> tp1{Make_To(1)};
    std::puts("# init and assign");
    std::tuple<To> tp2;
    tp2 = From{2};
    std::puts("# finish");
}

使用C++17编译后,输出结果如下:

-----------------
# direct init with conversion
From value constructor
value constructor
# direct init with creator
value constructor
move constructor
destructor
# init and assign
default constructor
From value constructor
value constructor
move assign
destructor
# finish
destructor
destructor
destructor

我将创建并赋值的情况作为RVO无法完全生效的参考场景(因为目标对象已开始生命周期)。想了解为什么类转换初始化与工厂函数初始化之间存在差异?


扩展示例

将std::tuple替换为简单的Wrapper后,代码如下:

struct Wrapper {
    Wrapper(To&& Input) : val(Input) {
        std::puts("Wrapper To&& constructor");
    };
    Wrapper(const To& Input) : val(Input) {
        std::puts("Wrapper const To& constructor");
    };

   private:
    To val;
};

int main() {
    std::puts("-----------------");
    std::puts("# Wrapper direct init with conversion");
    const Wrapper d0(From{0});
    std::puts("# Wrapper direct init with creator");
    const Wrapper d1(Make_To(1));
    std::puts("-----------------");
    std::puts("# finish");
}

编译后输出结果:

-----------------
# Wrapper direct init with conversion
From value constructor
value constructor
copy constructor
Wrapper from To&& constructor
destructor
# Wrapper direct init with creator
value constructor
copy constructor
Wrapper from To&& constructor
destructor
-----------------
# finish
destructor
destructor

这与std::tuple版本的输出差异很大,而我原本预期结果一致,这是为什么?


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 05:01:04