A question for the C ++ standards guru - what the current standard says about such code, which is fully compiled by both VC ++ and GCC :

#include <iostream> #include <iomanip> using namespace std; class Test { public: Test() { cout << "Test()" << endl; } Test(int x):val_(x){ cout << "Test(" << x << ")" << endl; } Test(const Test& t):val_(t.val_) { cout << "Test(const Test& " << t.val_ << ")" << endl; } Test& operator = (const Test& t) { cout << "Test& operator = (const Test& " << t.val_ <<")" << endl; val_ = t.val_; return *this;} ~Test() { cout << "~Test()" << endl; } int val() const { return val_; } private: int val_ = 0; }; int main(int argc, const char * argv[]) { Test t = t; cout << t.val() << endl; } 

It turns out that we essentially create an object without initializing the fields, performing only copying the object into itself, i.e. garbage in its place?

  • This is UB, it was already in Ruso, only you need to search - ixSci
  • @ixSci Yes, I guess :), but I would like to know exactly where (and how) is indicated, and why not explicitly prohibit it? Expensive to check? - Harry
  • UB because it is using an uninitialized variable in val_(t.val_) . Why they won't prohibit it - I don’t know, probably because it’s the corner case and there’s no point in fooling around with it. - ixSci

1 answer 1

Such an ad has undefined behavior.

Review the program

 struct A { A() : n(0), p(nullptr) {} A(const A &a) : n(an), p(new int[n]) { for (size_t i = 0; i < n; i++) this->p[i] = ap[i]; // std::copy(ap, ap + n, this->p); } ~A() { delete[] p; } size_t n; int *p; }; int main() { A a = a; } 

So neither the value of n , nor the value of p were initialized, and the copy constructor is called, copying an object into itself, then there will be an attempt to allocate dynamically the memory for an array of indeterminate size and addressing an address that has an undefined value.

C ++ standard is written (12.7 Construction and destruction)

For an object that has been defined as a non-trivial constructor

The C standard, which is also a regulatory document for the C ++ standard, also mentions that (6.2.6 Representations of types)

5 Certain object representations need not represent a value of the object type. It is a type of behavior that is undefined. It is a fact that it modifies the pattern.

In the above example, the class members are used before the constructor is called, since they were not initialized by the constructor when they are called in the copy constructor to be used to initialize the newly created class members. In addition, these class members may have so-called traps.

  • Thank you, I somehow did not take it as use before initialization :) - Harry
  • @Harry Not at all. Glad to answer. - Vlad from Moscow