Reputation: 321
While making a small parser for a project, I kept getting Segmentation Faults... tracked it down to a transposition typo.
This code sample is NOT the original code but reproduces the fault.
I was surprised that none of my compilers spotted that the reference is uninitialized.
Both GCC and Clang appear to compile it without warning or error.
Shouldn't they be flagging the REFERENCE TO v2 as uninitialized?
I'm relatively new to C++ and am learning C++17/20. But I am curious as to why, in this case, the compilers aren't spotting that v2 is undefined but passing a reference to an undefined object anyhow.
#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";
}
Upvotes: 0
Views: 105
Reputation: 122984
If this would not compile then one could also not do the following, which is not too uncommon:
struct base {
int& x;
base(int& x) : x(x) {}
};
struct foo : base {
int x;
foo() : base(x) {}
};
At the time the base
constructor is called, x
is not yet initialized, yet it is completely valid to store a reference to it for later use.
This is just one example where getting a reference to a not yet initialized object is just fine and forbidding to do this would require to write very unclear cumbersome code.
Upvotes: 6