Условия для копирования elision? - PullRequest
10 голосов
/ 17 июня 2011

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

  • RVO
  • Именованный RVO
  • Копировать elision при передаче аргумента по значению

Итак, я написал эту маленькую программу:

#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;
}

И я скомпилировал ее с включенной оптимизацией:

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

Это вывод:

Test RVO: 

Test named RVO: 

Test PassByValue: 
*** COPY ***

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

Согласно выходному RVO и названному RVO работают как положено.Однако исключение копирования не выполняется для оператора присваивания и при вызове PassByValue.

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

Ответы [ 2 ]

10 голосов
/ 17 июня 2011

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

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

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

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

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

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

9 голосов
/ 17 июня 2011

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...