2015-11-23 5 views
6

УчитываяБудет ли какой-нибудь компилятор действительно удалять эти копии?

struct Range{ 
    Range(double from, double to) : from(from), to(to) {} 
    double from; 
    double to; 
    // if it matters to the compiler, we can add more fields here to make copying expensive 
}; 

struct Box{ 
    Box(Range x, Range y) : x(x), y(y) {} 
    Range x; 
    Range y; 
}; 

someone said что в Box box(Range(0.0,1.0),Range(0.0,2.0)), компилятор может избежать копирования Range объектов в целом, построив их в box, чтобы начать с.

Выполняет ли какой-либо компилятор это?

Мои собственные попытки не удались.

+1

Если ваш компилятор является нисходящим, будьте уверены. Он будет им доверять. – 101010

+1

@ 101010 Хорошие ли современные компиляторы? Я не могу этого добиться. – Museful

+1

Вы должны комментировать этот ответ, не задавая повторяющийся вопрос. – LogicStuff

ответ

8

Компилятор может - и обычно делает - удаляет копии с временного аргумента. Компилятор не может передать копию аргумента членам. Хотя в некоторых случаях технически возможно исключить эти копии, соответствующее разрешение не предоставляется. Часть стандарта 12,8 [class.copy] пункт 31, который излагает 4 ситуации, когда копия может быть Опущенные (точные правила немного нетривиально):

  1. При возврате именованный, локальная функция переменной, используя это имя.
  2. При использовании имени, локальной переменной функции в выражении throw.
  3. При копировании временного объекта.
  4. При перехвате исключения по значению.

Передача именованного аргумента как параметра в конструкцию переменной-члена, очевидно, ни в одной из этих ситуаций.

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

+0

В дополнение к вышесказанному (очень хорошему) ответу я хотел бы добавить, что одним из способов оставаться под контролем является использование (возможно, const) ссылки или указателей указателя и только копирование, когда это действительно необходимо. Таким образом, вы точно знаете, что происходит, и не создаются лишние копии, и вы в основном не зависимы от того, что автор сценария сделал с точки зрения оптимизации. Кроме того, вам не нужно пытаться расшифровывать трудночитаемые документы стандартов. –

+0

@ ErikAlapää, используя ссылки const, мешает семантике перемещения; Я бы сказал, что здесь лучше перейти по цене. В этом конкретном коде мы можем заменить 'x (x)' на 'x (std :: move (x))' и т. Д., Что приводит к (для каждого параметра) 2 ходу, из которых 1 можно отбросить; но при переходе на константные ссылки есть одна копия, которую нельзя исключить. –

+0

@MM Интересно - я начинаю понимать rvalue refs и std :: move, но я все же склонен использовать проверенные методы старого стиля;) Но все же, если я использую указатель, я могу убедиться, что я минимизирую копирование, поскольку Мне явно нужно скопировать, чтобы получить копию. –

0

Это кто-то я. Позвольте мне очистить стенд.

Я никогда не говорил, что в Box box(Range(0.0,1.0),Range(0.0,2.0)) компилятор может избежать копирования объектов диапазона всего, создав их внутри коробки для начала. То, что я сказал, было:

Да, может, в частности, этот вид контекста копия Elision подпадает под критерий копирования Пропуска, указанного в 12,8/p31.3 Копирование и перемещение объектов класса [class.copy] стандарта:

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

Да, может, часть идет для временных объектов, передаваемых в конструктор (Это может быть игнорировать в соответствии со стандартом, как упоминалось выше).Я никогда не говорил, что параметры можно отбросить до списка инициализаторов конструктора Box.

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

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

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

  • Нет связанных вопросов^_^