在为项目制作小型解析器时,我不断遇到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";
}
答案 0 :(得分:6)
如果无法编译,则还不能执行以下操作,这种情况并不太常见:
struct base {
int& x;
base(int& x) : x(x) {}
};
struct foo : base {
int x;
foo() : base(x) {}
};
在调用base
构造函数时,x
尚未初始化,但是完全存储对它的引用以供以后使用是完全有效的。
这只是一个示例,其中获得对尚未初始化的对象的引用就很好,并且禁止这样做将需要编写非常不清楚的繁琐代码。