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

自定义构造函数中fenwick_tree结构体成员是否被构造两次?

问题分析与解答

相关代码

PhiBlock 结构体定义

struct PhiBlock
{   
    int64_t bsize;              // block size
    vector<int64_t> ind;        // 0/1 to track [pmin(y) > pb]
    fenwick_tree phi_sum;       // partial sums

    PhiBlock (int64_t bsize, int64_t a):
        phi_sum(ind)
    {
        this->bsize = bsize;
        ind.resize(bsize, 1);
        phi_sum = fenwick_tree(ind);
    }
    // ...
};

fenwick_tree 结构体定义

struct fenwick_tree
{
    size_t len; // 0-based len
    std::vector<int64_t> t; // 1-based tree, indexes [1:len]

    fenwick_tree(std::vector<int64_t> const &a)
    {
        len = a.size();
        t.assign(len + 1, 0);
        for (size_t i = 0; i < len; ++i)
            add_to(i, a[i]);
    }

    // ...
};

疑问与解答

1. 对初始化流程的理解是否正确?

你的理解完全正确:

  • 由于fenwick_tree没有默认构造函数,必须在成员初始化列表中显式初始化phi_sum,此时ind是默认构造的空vector,因此第一次构造的phi_sum是基于空容器的实例;
  • 进入构造函数体后,ind被resize为指定大小并填充1;
  • 最后通过fenwick_tree(ind)创建临时对象,再赋值给phi_sum,完成第二次构造(临时对象)+ 赋值操作。

2. phi_sum 是否必须被构造两次?

在当前代码结构下,是的。成员初始化阶段必须完成phi_sum的构造(无默认构造函数时编译器无法自动初始化),但此时ind还未被初始化到目标状态,只能先基于空ind构造一次,后续再通过赋值替换。

不过可以通过调整代码避免两次构造:将ind的初始化移到成员初始化列表中,直接用正确状态的ind构造phi_sum,示例如下:

PhiBlock (int64_t bsize, int64_t a):
    bsize(bsize),
    ind(bsize, 1),
    phi_sum(ind)
{}

这样只需构造一次phi_sum,完全避免后续赋值操作。

3. 给fenwick_tree添加默认构造函数后,是否无需成员初始化列表?

是的。如果给fenwick_tree添加空操作的默认构造函数(比如初始化空vector、设置len=0),编译器会自动在成员初始化阶段调用默认构造函数初始化phi_sum,此时无需在初始化列表中显式声明phi_sum的初始化,后续可在构造函数体中对phi_sum进行赋值或重新初始化。

关于优化的补充

未开启-O2时,确实能看到两次fenwick_tree构造操作;开启-O2后,编译器可能会优化掉后续的赋值操作(比如直接修改第一次构造的phi_sum实例,而非创建临时对象再赋值),但这属于编译器的优化行为,不能依赖它保证代码正确性或性能,建议从代码结构上避免不必要的构造。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 06:03:11