2015-03-04 15 views
5

Odkryłem, że kompilator Intel nie generuje optymalizacji wartości zwracanej dla obiektów std :: array. Poniższy kod, który znajduje się w wewnętrznej pętli mojego programu, nie jest zoptymalizowany, tak jak mógł.Czy Optymalizacja wartości zwracanej musi zadeklarować konstruktora kopiowania

std::array<double, 45> f(const std::array<double, 45>& y) { 
    auto dy_dt = std::array<double, 45>(); 
    ... 

    return dy_dt; 
} 

I zorientowali się, że takie zachowanie wynika z faktu, że moja średnia realizacja biblioteka nie jawnie zdefiniować konstruktor kopiujący dla std :: tablicy. Poniższy kod demonstruje, że:

class Test { 
public: 
    Test() = default; 
    Test(const Test& x); 
}; 

Test f() { 
    auto x = Test(); 

    return x; 
} 

Podczas kompilowania go

icpc -c -std=c++11 -qopt-report=2 test.cpp -o test.o 

plik raport pokazuje

INLINE REPORT: (f(Test *)) [1] main.cpp(7,10) 

co dowodzi, że kompilator generuje RVO (podpis f ulega zmianie dzięki czemu może umieścić nowo utworzony obiekt na stosie strony wywołującej). Ale jeśli wykomentuj wiersz deklaruje Test(const Test& x); plik raport pokazuje

INLINE REPORT: (f()) [1] main.cpp(7,10) 

co dowodzi, że RVO nie jest generowany.

W 12.8.31 standardu C++ 11, który definiuje RVO, przykład, który podają, ma konstruktora kopii. Czy jest to "błąd" kompilatora Intela lub zgodna implementacja standardu?

+0

@Cyber ​​Nie, gdyby RVO było możliwe, to usunąłoby kopię. – juanchopanza

+0

Cyber: Nie, ta funkcja nazywa się optymalizacją wartości zwracanej. Nie ma nic wspólnego z semantyką ruchu. – InsideLoop

+0

RVO nie potrzebuje konstruktora kopiowania jako takiego, ale kod, którego dotyczyłaby aplikacja RVO, musi mieć dostępny poprawny konstruktor kopii lub przeniesienia. – juanchopanza

Odpowiedz

1

Ten program powoduje niezdefiniowane zachowanie bez diagnostyki wymaganej z powodu naruszenia zasady jednej definicji.

Konstruktor kopiujący to odr-used przy powrocie według wartości - even if copy elision takes place.

Funkcja nieinstancji inline to odr-used oznacza, że ​​dokładnie jedna definicja funkcji musi pojawić się w programie. Jednak podałeś żadnej, a twoja deklaracja konstruktora kopiowania pomija definicję generowaną przez kompilator.

+0

Myślę, że to prawdopodobnie dlatego, że nie cały kod jest pokazany. On także nie zapewnił głównej roli. Hipotetycznie może istnieć inny plik test2.cpp, którego nie pokazano ani nie wspomniano, który ma definicję tego konstruktora kopii. Lub może być w main.cpp. – thang

+0

@Matt: Nie rozumiem twojego punktu widzenia. Jeśli nie zdefiniujesz konstruktora kopiowania, standard definiuje go dla ciebie. – InsideLoop

+0

@InsideLoop no; jeśli nie * deklarujesz * konstruktora-kopii, kompilator deklaruje i definiuje go dla ciebie. Ponadto, jak wskazuje na to Ethang, przydatne byłoby opublikowanie ważnego programu (lub próba wykonania jednego z nich). Nie można zgłosić raportu błędu optymalizacji na podstawie programu, który nie kompiluje. –

Powiązane problemy