2015-04-23 5 views
20

Является ли поведение следующего кода четким?Ссылка на объект перед построением

struct X { int i; }; // trivial 
struct Y : X { Y(){} }; // non-trivial 

extern X xobj; 
int& r1 = xobj.i; // #1 
X xobj; 

extern Y yobj; 
Y& r2 = yobj;  // #2 
// int& r3 = yobj.i; // #3 - this is UB according to the standard 
Y yobj; 

Этот код вдохновлен, например, в стандарте С ++, а именно проект N4140 [class.cdtor]/1.

Вот что гласит, что пункт:

Для объекта с нетривиальным конструктором, обращаясь к любому нестатического члену или базовый классу объекта перед конструктором начинает результаты выполнения в непредсказуемом поведении. Для объекта с нетривиальным деструктором , ссылаясь на любой нестатический член или базовый класс объекта после завершения выполнения деструктора , результат приводит к неопределенному поведению.

Ниже приведен пример, который показывает, как указатели могут и не могут быть связаны с объектами.

Так интуитивно кажется, что #1 и #2 хорошо определены, в то время как #3 вызывает UB, если раскомментировать, но, во-первых, примеры не являются нормативными, во-вторых, нет никакого упоминания ссылок в данном примере, и третье, и самое важное , вышеприведенный параграф не означает, что в противном случае поведение четко определено. Или это? Или, может быть, есть другая соответствующая цитата в стандарте, который я пропустил?

Edit: Ответ может (возможно) будет да, если объекты имеют статическую продолжительность хранения, но они могут быть также локальным, например:

struct A { A(){} }; 
struct B { B(A&){} }; 

struct C { 
    B b; 
    A a; 
    C() : b(a) {} 
}; 

int main() { 
    C c; 
} 

На самом деле это было первоначальное вдохновение для этого вопроса, см Circular dependency in constructor initialization list

+3

«обращение к любому нестационарному члену [...] приводит к неопределенному поведению» - ссылка - это именно то, что делает ссылка (отсюда и название). – molbdnilo

+0

@molbdnilo Я это понимаю, но это не объясняет, что происходит * в противном случае * (например, ссылаясь на ... до того, как конструктор начнет для класса с тривиальным конструктором), вот в чем вопрос. –

+0

«ссылаясь на это» означает упоминание об этом (это английское слово «refer»). –

ответ

0

[...] нет упоминания ссылок в примере [...]

Вы имеете в виду, кроме

[...] со ссылкой на любой не статический член [...]

Из отрывка вы цитируете, я бы сказал, что линия причин неопределенное поведение:

int& r3 = yobj.i; // #3 

, потому что вы:

[...] со ссылкой на любой нестатический член или базовый класс объекта до конструктора начинается выполнения

Кроме того, для этого [.]:

и самого главного, выше, не означает, что в противном случае поведение четко определено.

Вы правы, это не делает:

Неопределенное поведение можно ожидать, когда этот международный стандарт отсутствует какая-либо четкое определение поведения или когда программа использует ошибочную конструкцию или ошибочные данные, ,

+0

# 3 вызывает UB, в этом нет никаких сомнений. Но # 2 (интуитивно) эквивалентно 'Y * p2 = & yobj', который четко обозначен как хорошо определенный в стандартном примере (но не в нормативном тексте) –

+0

Это? Что означает «базовый класс» тогда, если не 'yobj'? – Siguza

+0

Возможно, что ссылки на нестатические элементы данных и базовые классы - это UB из-за виртуальных базовых классов. Vtable настроен во время строительства, поэтому вы не можете получить доступ ни к элементам, ни к виртуальным базовым классам до начала строительства. – dyp

2

Поведение № 2 определенно определено. Как отметил @dyp, соответствующий пункт в [basic.life]:

enter image description here

Связывание glvalue yobj к опорному нормально, так как его хранение длится в течение всего срока действия программы ([основной. stc.static]/1), и ссылка привязана к действительной стороне объекта - в соответствии с требованиями в ([dcl.ref]/5). Аналогичным образом, для второго примера, который вы указали, пока не выполняется никакая операция для членов подобъекта A, приведенный выше параграф применяется также, так как конструктор C вызывается в выделенном хранилище this.