【问题标题】:C++ vector stack overflow in constructor构造函数中的 C++ 向量堆栈溢出
【发布时间】:2021-12-30 21:57:49
【问题描述】:

我有以下代码sn-p:

#include <vector>

struct X {
    std::vector<X> v;
    X(std::vector<X> vec) : v{vec} {}
};

int main() {
    X{{}};
}

在本地编译和运行这个 sn-p 会导致源自 X 的构造函数的堆栈溢出。使用gdb 进行检查显示构造函数以某种方式递归调用自身,但这没有意义,因为我没有递归调用它。为什么会发生这种情况,我可以做些什么来解决它?

【问题讨论】:

  • X 包含几个(向量的)X?这是树形结构吗?
  • @Sebastian 是的,它是一个递归树结构。

标签: c++


【解决方案1】:

问题与 C++ 如何选择要执行的构造函数有关。请注意X 的构造函数在成员初始化列表中使用花括号语法,这意味着它使用列表初始化语法。根据C++ reference

当非聚合类类型 T 的对象被列表初始化时,会发生两阶段重载决议。

  • 在第 1 阶段,候选函数都是 T 的初始化列表构造函数,用于重载决策的参数列表由单个初始化列表参数组成
  • 如果重载决议在阶段 1 失败,则进入阶段 2,其中候选函数都是 T 的构造函数,并且用于重载决议的参数列表由初始值设定项列表的各个元素组成。

如果初始化列表为空且 T 有默认构造函数,则跳过第 1 阶段。

在复制列表初始化中,如果第 2 阶段选择显式构造函数,则初始化格式不正确(与完全不考虑显式构造函数的复制初始化相反)。

std::vector 有一个初始化列表构造函数,如 here 所示,因此该构造函数在上述阶段 1 中具有优先级。在问题中,X 的非显式构造函数意味着提供的向量 vec可以隐式转换为X,因此可以应用向量构造函数。由于这个隐式转换调用了X 的构造函数,所以你最终得到了上面描述的递归。

要解决此问题,mark X's constructor as explicitswitch to v(vec) syntax in the constructor

【讨论】:

    猜你喜欢
    • 2012-06-15
    • 2015-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-10
    • 2014-12-28
    • 2012-12-20
    相关资源
    最近更新 更多