#cpp #cpp11 #cpp14
Вопрос к гуру по стандартам C++ - что нынешний стандарт говорит о таком коде, вполне компилируемом и VC++, и GCC: #include#include 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; } Получается, что мы по сути создаем объект без инициализации полей, выполняя только копирование объекта в самого себя, т.е. мусора на свое же место?
Ответы
Ответ 1
Такое объявление имеет неопределенное поведение. Рассмотрите программу struct A { A() : n(0), p(nullptr) {} A(const A &a) : n(a.n), p(new int[n]) { for (size_t i = 0; i < n; i++) this->p[i] = a.p[i]; // std::copy(a.p, a.p + n, this->p); } ~A() { delete[] p; } size_t n; int *p; }; int main() { A a = a; } Так ни значение n , ни значение p не были инициализированы, а при этом вызывается конструктор копирования, копирующий объект в сам себя, то будет иметь место попытка выделения динамически памяти для массива неопределенного размера и обращение по адресу, который имеет неопределенное значение. В стандарте C++ написано (12.7 Construction and destruction) 1 For an object with a non-trivial constructor, referring to any non-static member or base class of the object before the constructor begins execution results in undefined behavior. В стандарте C, который является нормативным документом также для стандарта C++ также упоминается, что (6.2.6 Representations of types) 5 Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does ot have character type, the behavior is undefined. If such a representation is produced by a side effect that modifies all or any part of the object by an lvalue expression that does not have character type, the behavior is undefined.50) Such a representation is called a trap representation. В приведенном примере выше, члены класса используются до вызова конструктора, так как они не были инициализированы конструктором, когда идет обращение к ним в конструкторе копирования, чтобы их значения использовать для инициализации создаваемых членов класса нового объекта. Кроме того эти члены класса могут иметь так-называемые trap-представления.
Комментариев нет:
Отправить комментарий