C ++ 17编译器是否应该发现未定义值的按引用传递?

时间:2018-09-19 13:15:08

标签: c++ gcc compilation clang pass-by-reference

在为项目制作小型解析器时,我不断遇到Segmentation Faults ...一直跟踪到换位错误。

此代码示例不是原始代码,但是会重现错误。

令我惊讶的是,我的编译器都没有发现引用未初始化。

GCC和Clang似乎都在没有警告或错误的情况下对其进行了编译。

他们不是应该将 REFERENCE TO v2标记为未初始化吗?

我对C ++比较陌生,正在学习C ++ 17/20。 但是我很好奇为什么在这种情况下,编译器没有发现v2是未定义的,而是无论如何都会传递对未定义对象的引用。

#include <iostream>
#include <vector>
struct A
{
    using vectorA = std::vector<A>;
    int     foo;
    vectorA vA;

    A() = delete; // Implicit but let's be certain!

    A(int f) noexcept
        : foo {f},
          vA  {}
    {}
};

A::vectorA& recurse(A::vectorA& head, int tail) noexcept
{head.emplace_back(tail); return head;}

int main()
{
    // A tree of A's
    A::vectorA v1 {};

    // Fill it using recursive fn converting bars into foos,
    // a bar at a time
    int bar {666};
    A::vectorA v2 {recurse(v2, bar)};
    //                      ^
    // typo of 'v2' instead of 'v1' still compiles!
    // SHOULD, of course, read; A::vector_of_A v2 {recurse(v1, bar)};
    //
    // But v2 is... what exactly? At the point it is passed to recurse?
    // It is uninitialized although it has an address and (likely) space       
    // allocated to hold it.
    // No warning?

    std::cout << "Should this compile?\n";
    std::cout << "Oops! Segmentation Fault Guaranteed!\n";
}

1 个答案:

答案 0 :(得分:6)

如果无法编译,则还不能执行以下操作,这种情况并不太常见:

struct base {
    int& x;
    base(int& x) : x(x) {}
};

struct foo : base {
    int x;
    foo() : base(x) {}
};

在调用base构造函数时,x尚未初始化,但是完全存储对它的引用以供以后使用是完全有效的。

这只是一个示例,其中获得对尚未初始化的对象的引用就很好,并且禁止这样做将需要编写非常不清楚的繁琐代码。