问题描述
给定
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;
};
有人说在Box box(Range(0.0,1.0),Range(0.0,2.0))
,编译器可以通过在 box
内部构造它们来避免完全复制 Range
对象.
someone said that in Box box(Range(0.0,1.0),Range(0.0,2.0))
, the compiler can avoid copying Range
objects altogether by constructing them inside box
to begin with.
真的有编译器这样做吗?
Does any compiler actually do this?
我自己的尝试没有成功.
My own attempts haven't succeeded.
推荐答案
编译器可以 - 并且通常会 - 删除从临时到参数的副本.编译器不能删除从参数到成员的副本.虽然在某些情况下在技术上可以删除这些副本,但未获得相关许可.该标准的部分是 12.8 [class.copy] 第 31 段,其中阐明了可以省略副本的 4 种情况(确切的规则有点重要):
The compiler can - and normally does - elide the copies from the temporary to the argument. The compiler cannot elide the copy from the argument to members. While it may technically possible to elide these copies in some cases, the relevant permission isn't given. The section of the standard is 12.8 [class.copy] paragraph 31 which spells out 4 situations where a copy can be elided (the exact rules are a bit non-trivial):
- 当返回一个命名的函数局部变量时,使用它的名字.
- 在
throw
表达式中使用命名的函数局部变量时. - 复制临时对象时.
- 按值捕获异常时.
- When returning a named, function local variable using it name.
- When using a named, function local variable in a
throw
expression. - When copying a temporary object.
- When catching an exception by value.
将命名参数作为参数传递给成员变量的构造显然不是这些情况.
Passing a named argument as parameter to the construction of a member variable is, clearly, none of these situations.
复制省略规则的基本背景是,在某些上下文中,函数声明足以确定何时使用对象.如果在构建时间明确可以构建对象,则可以省略它.构造函数的调用者不能仅根据构造函数的声明来确定将在何处使用该对象.
The essential background of the rules for copy elision is that in some contexts the declaration of functions suffice to determine when an object will be used. If it is clear upon construction time where the object can be constructed, it can be elided. The caller of a constructor cannot determine based only on the declaration of the constructor where the object will be used.
这篇关于任何编译器实际上会忽略这些副本吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!