嵌套的C 常数数据结构,没有初始化列表或明确命名所有节点-VC 2012过早破坏了内部元素

Nested C++ constant data structures without initializer lists or explicitly naming all nodes -- VC++2012 destroys inner elements prematurely?

本文关键字:2012 -VC 节点 内部 元素 坏了 数据结构 常数 列表 初始化 嵌套      更新时间:2023-10-16

因此,我正在尝试使用该问题的答案中的方法来实现C 中的大,有点宽,恒定的树结构(使用VC 2012,V110工具链),如下所示:

#include <tuple>
#include <iostream>
struct test
{
    test(const char* n, const test& n1, const test& n2):
        name(n), nodes(n1, n2)
    {
        if (name)
            std::cerr << "test() " << name << std::endl;
    }
    ~test()
    {
        if (name)
            std::cerr << "~test() " << name << std::endl;
    }
    const char* name;
    std::tuple<const test&, const test&> nodes;
};
const test n = test(0, n, n);
test t = test("blah", test("bleh", n, n), n);
int main()
{
    std::cerr << "get " << std::get<0>(t.nodes).name << std::endl;
    return 0;
}

但是,而不是输出预期

test() bleh
test() blah
get bleh
~test() bleh
~test() blah

或那个同类的东西,我得到

test() bleh
test() blah
~test() bleh
get

然后,当该程序试图访问过早破坏的内部对象时,程序(即窗口"此程序已经停止工作"框停止工作框)死亡。这是我假设将临时的一个临时参考持有另一个对象的临时参考子对象以与本地或全局命名的const引用相同的方式延长寿命的错误吗?还是VC 2012的问题不是意识到应该这样做的临时性在父对象构造函数中通过引用捕获(即,直到外部对象被处置为止?)

这个位: std::get<0>(t.nodes).name永远不会在当前代码中正常工作,无论发生什么事。那是因为nodes包含参考:std::tuple<const test&, const test&>而不是实例。

由于您传递内在对象时的结果:test("bleh", n, n)时,它不会复制到外部一个的nodes中。因此,当它脱离范围并且被销毁时,您的外部对象的nodest.nodes)包含指向大范围的引用。结果,您的程序将在该语句中例外,并使用segfault崩溃。

编辑要添加:

澄清:超出范围的对象是: test("bleh", n, n)

的值

在此语句中:test t = test("blah", test("bleh", n, n), n);

因为到t = test("blah",...)返回时,内在对象test("bleh",...)已经消失了。请注意,t实际上是test("blah",...)值的副本,原始临时性也消失了。(当您考虑编译器可以选择优化和进行移动而不是副本时,它会变得更加复杂,但是语义似乎是副本。)