Dav*_*rry 0 c++ gcc compilation clang pass-by-reference
在为项目制作一个小解析器时,我不断收到Segmentation Faults ...跟踪它转换为转置错误.
此代码示例不是原始代码,但会重现故障.
我很惊讶我的编译器都没有发现引用是未初始化的.
GCC和Clang似乎都在没有警告或错误的情况下编译它.
难道他们不应该将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";
}
Run Code Online (Sandbox Code Playgroud)
如果这不能编译,那么也可能不会执行以下操作,这并不常见:
struct base {
int& x;
base(int& x) : x(x) {}
};
struct foo : base {
int x;
foo() : base(x) {}
};
Run Code Online (Sandbox Code Playgroud)
在base
调用构造函数时,x
尚未初始化,但是存储对它的引用以供以后使用是完全有效的.
这只是一个例子,其中获取对尚未初始化的对象的引用是正常的并且禁止这样做将需要编写非常不清楚的繁琐代码.