2014-02-18 5 views
4
class A { 
public: 
    A() { cout << "A()" << endl; } 
}; 
class B { 
public: 
    A a; 
    B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; } 
    /* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */ 
}; 
int main() { 
    B b(A()); /* no ouput */ 
} 

Для вышеуказанного кода выхода не генерируется. Это связано с оптимизацией компилятора (копия elision), как обсуждалось в этом link?Конструктор не вызывается в этом классе агрегации

Но если у меня есть класс B конструктор и переписать код, как показано ниже:

class A { 
public: 
    A() { cout << "A()" << endl; } 
}; 
class B { 
public: 
    A a; 
    B() {} 
    B(const A& a1) : a(a1) { cout << "B(const A&)" << endl; } 
    /* B(const A& a1) { a = a1; cout << "B(const A&)" << endl; } */ 
}; 
int main() { 
    B().a; // gives output A() 
} 
+11

'B b (A());' Это объявление функции. Найдите «самый неприятный синтаксический разбор». – jrok

ответ

1
B b(A()); 

неоднозначен и может быть истолковано либо как при объявлении переменной или как объявление функции, возвращает результат восстановления типа B и принимает один неназванный параметр типа - функция без параметров и возвращает результат типа A. Хотя вы, возможно, думаете, что сначала следует иметь в виду, что стандарт диктует на самом деле второй случай. См. Статью о most vexing parse в Википедии.

3

добавить дополнительную пару скобок:

B b((A())); 

// you can also fix it using new C++11 initialization syntax: 
B b{A()}; 

проблемы вы столкнулись это называется наиболее неприятным разобрана, и это означает, что компилятор не может решить, хотите ли вы объявление функции или определение переменного.

[править]

Я должен также добавить, что стандарт требует компилятор в таком случае выбрать объявление функции.

[править]

лязг на самом деле более полезным в этом случае, и дает намек на использование partentheses:

http://rextester.com/PECQ53431

source_file.cpp:16:8: warning: parentheses were disambiguated as a function declaration [-Wvexing-parse] 
    B b(A()); /* no ouput */ 
     ^~~~~ 
source_file.cpp:16:9: note: add a pair of parentheses to declare a variable 
    B b(A()); /* no ouput */ 
     ^
     () 

1 предупреждение генерируется.

+0

"компилятор не может решить" Это неправда. Он прекрасно знает. – jrok

+0

@jrok Ну, точно говоря, компилятор не может решить, какой из них вы хотите. * Он прекрасно знает, какой из них вы * написали. * ;-) – Angew

+0

@jrok Eh, синтаксис неоднозначен, стандартный говорит, что в таком случае он должен выбрать «объявление функции». – Xarn

0

Вместо создания объекта после создания объекта B сначала создайте объект A s.

A a; 
B b(a); 
Смежные вопросы