2012-02-29 5 views
6

Почему вывод следующей программы только int3, а не int3&4?Конструктор копирования с параметрами по умолчанию никогда не называется

#include <iostream> 

class B 
{ 
public: 
    explicit B(int i) { std::cout<<"int"<<i; } 
    B(const B& rhs, int i = 0) { std::cout<<"&"<<i; } 
}; 

int main(int, char**) 
{ 
    B b(B(3), 4); 
} 

Команда: clang++ test.cpp -O0

Компилятор: Apple лязг версия 3.0 (теги/Apple/лязг-211,12) (на основе LLVM 3.0svn)

+0

Он печатает 'int3 & 4' для меня (GCC 4.6.2,' -O3'). –

+0

На самом деле, мой g ++ 4.6.1 печатает «int3 & 4». – Duck

+1

+1 для короткого, полного тестового случая. http://sscce.org –

ответ

1

Это был bug in clang, в котором есть since been fixed. Копирование-исключение было неправильно применено к вызову конструктора, потому что clang не проверял, сколько аргументов было предоставлено, прежде чем заключить, что это была конструкция копии.

Исправление будет в предстоящем выпуске clang 3.1.

3

Похоже, вы нашли компилятор причуду:)

Если вы изменили свою версию компилятора ничего, что не LLVM 3.0, выход Int3 & 4.

Печатается я NT3 & 4 на LLVM 3.0, так что, похоже, связано с тем, что B (3) представляет собой временный объект:

class B 
{ 
public: 
    explicit B(int i) 
    { 
     std::cout<<"int"<<i; 
    } 
    B(const B& rhs, int i = 0) 
    { 
     std::cout<<"&"<<i; 
    } 
}; 

int main(int, char**) 
{ 
    B a(3); 
    B b(a, 4); 
} 
+0

Да, это была ошибка в clang, которая с тех пор была исправлена. Копирование-исключение было неправильно применено к вызову конструктора, потому что clang не проверял, сколько аргументов было предоставлено, прежде чем заключить, что это была конструкция копии. –

+0

@RichardSmith Можете ли вы разместить этот комментарий в качестве ответа? –

0

Скорее всего, РВО и NRVO съела свой код. Эти особые условия позволяют компилятору молча удалять копии объектов, которые в противном случае были бы соблюдены языком. Поскольку в результате не было сделано никакой копии, код никогда не печатает инструкцию в конструкторе копирования.

+0

Можно ли разрешить RVO и NRVO даже в режиме отладки? Насколько я понимаю, они оптимизированы и поэтому должны быть отключены при работе в режиме отладки, но в режиме отладки я тоже получаю «int3», на LLVM 3.0 – Carl

+0

Просто подумал, что добавлю следующее: http://stackoverflow.com/ вопросы/8556608/что-может-я-разумно ожидать-а-компилятор-к-быть в состоянии к инлайн. По-видимому, некоторые компиляторы также выборочно реализуют RVO и/или NRVO в режиме отладки, что объясняет поведение LLVM. – Carl

+0

@ carleeto: Компилятор может юридически делать это, когда захочет. – Puppy

Смежные вопросы