2011-06-17 1 views
10

Я хотел проверить, если выполняются следующие оптимизации работы, как и ожидалось:Условия для копирования elision?

  • РВО
  • Названный РВО
  • Copy элизия при передаче аргумента по значению

Так что я написал эту небольшую программу :

#include <algorithm> 
#include <cstddef> 
#include <iostream> 
#include <vector> 

struct Foo { 
    Foo(std::size_t length, char value) : data(length, value) { } 

    Foo(const Foo & rhs) : data(rhs.data) { std::cout << "*** COPY ***" << std::endl; } 

    Foo & operator= (Foo rhs) { 
     std::cout << "*** ASSIGNMENT ***" << std::endl; 
     std::swap(data, rhs.data); // probably expensive, ignore this please 
     return *this; 
    } 

    ~Foo() { } 

    std::vector<char> data; 
}; 

Foo TestRVO() { return Foo(512, 'r'); } 

Foo TestNamedRVO() { Foo result(512, 'n'); return result; } 

void PassByValue(Foo inFoo) {} 

int main() 
{ 
    std::cout << "\nTest RVO: " << std::endl; 
    Foo rvo = TestRVO(); 

    std::cout << "\nTest named RVO: " << std::endl; 
    Foo named_rvo = TestNamedRVO(); 

    std::cout << "\nTest PassByValue: " << std::endl; 
    Foo foo(512, 'a'); 
    PassByValue(foo); 

    std::cout << "\nTest assignment: " << std::endl; 
    Foo f(512, 'f'); 
    Foo g(512, 'g'); 
    f = g; 
} 

И я скомпилировал его с оптимизацией en недееспособных:

$ g++ -o test -O3 main.cpp ; ./test 

Это вывод:

Test RVO: 

Test named RVO: 

Test PassByValue: 
*** COPY *** 

Test assignment: 
*** COPY *** 
*** ASSIGNMENT *** 

Согласно выводу РВО и имени РВО работы, как и ожидалось. Однако для оператора присваивания не выполняется копирование, а при вызове PassByValue.

Не разрешено ли исключение копирования для определенных пользователем экземпляров-копий? (Я знаю, что RVO явно разрешено стандартом, но я не знаю о копировании elision при передаче по значению.) Есть ли способ проверить копию elision без определения конструкторов копирования?

+1

Просто, чтобы быть ясным, (N) RVO * есть * копия elision. Они не являются единственными формами, но сказать, что ваш пример показывает, что копирование не выполняется, является неточным. –

+0

Обычно для всех временных объектов разрешен эскиз cooy, но не для именованных или связанных объектов. Кажется, что gcc выполняет именно разрешенные. –

+0

@ Dennis Zickefoose спасибо, я исправил текст. – StackedCrooked

ответ

9

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

Если вы попытаетесь это таким образом, она могла бы работать лучше:

PassByValue(Foo(512, 'a')); 

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

+0

Оптимизация действительно выполняется здесь. Этот пример вместе с ответом @ Space_C0wb0y заставил меня получить его. – StackedCrooked

10

Стандарт говорит (в пункте 12.8.15):

Это элизия операций копирования является допускается в следующих обстоятельствах (которые могут быть объединены для устранения нескольких копий):

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

  • когда временный класс объекта не было связанно с ссылки (12.2) будет скопировано на объект класса с тем же CV-неквалифицированным типом, операция копирования может быть опущена с помощью построения TEMPO- объекта окон- чательны непосредственно в мишень опущена копия

Ни один из этих случаев применяется здесь, так что элизия не допускается. Первое - очевидно (нет возврата). Второе не разрешено, потому что объект, который вы проходите, не является временным.

Обратите внимание, что ваш код по-прежнему прекрасен, потому что вам все равно придется создавать копию. Чтобы избавиться от этой копии, вам нужно будет использовать семантику перемещения C++ 0x.

+1

В C++ 11 номер раздела становится §12.8/31, и есть еще 2 обстоятельства, при которых разрешено копирование/перемещение, но они относятся только к обработке исключений. – kennytm

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