问题标签 [copy-elision]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c++ - 为什么在返回参数时不允许 RVO?
在 [C++11: 12.8/31] 中有说明:
这种复制/移动操作的省略,称为复制省略,是允许的[...]:
— 在具有类返回类型的函数的 return 语句中,当表达式是具有与函数返回类型相同的 cv 非限定类型的非易失性自动对象(函数或 catch 子句参数除外)的名称时,可以通过将自动对象直接构造到函数的返回值中来省略复制/移动操作
这意味着
将打印
为什么需要第二个复制构造函数?编译器不能简单地延长x的生命周期吗?
c++ - 复制省略导致不同的结果
假设我有这种假设的、奇怪的和不直观的情况
我知道复制省略意味着a
将仅使用默认构造函数进行初始化,而 b 将使用复制构造函数进行初始化。我也知道(至少在 gcc 上)你可以告诉编译器不要做任何复制省略。
我的问题是有什么方法可以让编译器不只为这个类使用复制省略吗?
我意识到在任何实际情况下的答案都是 99.9% 的时间找到其他方式,而我没有 0.01% 的情况之一(这是一个实际的假设问题,而不是“假设问题”)
c++ - 这是复制构造函数省略吗?
以下代码不调用复制构造函数。
输出:
是copy-ctor省略吗?
c++ - 从工厂函数就地初始化不可复制的成员(或其他对象)
一个类必须有一个有效的复制或移动构造函数,这样的任何语法都是合法的:
在 C++03 中,依靠复制省略来防止编译器接触复制构造函数是相当普遍的。无论定义是否存在,每个类都有一个有效的复制构造函数签名。
在 C++11 中,一个不可复制的类型应该定义C( C const & ) = delete;
,无论使用如何,都会使对该函数的任何引用无效(对于不可移动的类型也是如此)。(C++11 §8.4.3/2)。一方面,GCC 在尝试按值返回这样的对象时会抱怨。复制省略不再有帮助。
幸运的是,我们还有新的语法来表达意图,而不是依赖漏洞。该factory
函数可以返回一个花括号初始化列表来临时就地构造结果:
编辑:如果有任何疑问,此return
语句解析如下:
- 6.6.3/2:“带有花括号初始化列表的返回语句通过指定初始化列表中的复制列表初始化 (8.5.4) 初始化要从函数返回的对象或引用。”
- 8.5.4/1:“复制初始化上下文中的列表初始化称为复制列表初始化。” ¶3:“如果 T 是类类型,则考虑构造函数。枚举适用的构造函数,并通过重载决议(13.3、13.3.1.7)选择最佳构造函数。”
不要被名称copy-list-initialization误导。8.5:
13:初始化的形式(使用括号或
=
)通常是无关紧要的,但当初始化器或被初始化的实体具有类类型时,它就很重要;见下文。如果被初始化的实体没有类类型,则带括号的初始化器中的表达式列表应为单个表达式。14:在表单
T x = a;
以及参数传递、函数返回、抛出异常(15.1)、处理异常(15.3)和聚合成员初始化(8.5.1)中发生的初始化称为复制初始化。
当初始化器是花括号初始化列表时,复制初始化及其替代方法直接初始化始终遵循列表初始化。添加 没有语义影响=
,这是列表初始化被非正式地称为统一初始化的原因之一。
有区别:与复制初始化不同,直接初始化可能会调用显式构造函数。复制初始化初始化一个临时对象,并在转换时将其复制以初始化对象。
语句的复制列表初始化规范return { list }
仅指定精确等效语法为temp T = { list };
,其中=
表示复制初始化。它并不立即暗示调用了复制构造函数。
-- 结束编辑。
然后可以将函数结果接收到右值引用中,以防止将临时复制到本地:
问题是,如何从返回不可复制、不可移动类型的工厂函数初始化非静态成员?引用技巧不起作用,因为引用成员不会延长临时成员的生命周期。
请注意,我不考虑聚合初始化。这是关于定义一个构造函数。
c++ - vector.push_back 右值和复制省略
我push_back
一个临时对象变成了vector
这样,
编译器是否会应用复制省略将临时对象A("abc")
直接构造到.vector
A
vec
c++ - 二元运算符+重载的返回值是否应该是 const 并且会干扰优化?
给定示例代码:
我开始怀疑 operator+() 是否应该实际返回一个 const Integer。Bruce Eckel 在“Thinking in C++”中为类似情况提供了运算符重载的示例,并且似乎支持返回类型上的 const 修饰符。应该使用它,为什么?
另一方面,让我们尝试使用这个类:
当将c创建为a和b的总和时,编译器很可能会执行复制省略,并且 Integer::operator+() 将直接在c占用的位置创建其结果(请参阅“想要速度?按值传递”)。但是当 Integer::operator+() 的返回类型声明为 const 时,由于目标是非常量的,这不会强制编译器执行复制吗?
c++ - 在 c++11 中,虚函数可以通过移动语义有效地返回一个大值吗?
通常,这将被优化为不涉及复制大值(因为 astd::vector
启用了移动语义):
如果函数是虚方法,是否也可以以相同的方式进行优化:
即,即使在运行时选择了被调用的函数,移动语义是否也有效?
c++ - 构造函数的链式调用中的复制省略
由于复制省略,通常首选按值传递对象,只要保留内部副本即可。以下情况怎么办:
链接的副本是否仍会被省略,即 1、3 和 5 更可取吗?或者更确切地说是2、4、6?它依赖于内联吗?
c++ - 理解 c++11 右值、移动语义和性能
考虑以下代码
该函数getName()
返回一个临时对象。在 C++03 中,我理解string
被调用的拷贝构造函数和临时对象被销毁。实际上,编译器(至少在 GCC 4.7 中)似乎通过不创建对象name
而是用临时对象本身替换它而不破坏临时对象来优化第 5 行。(我尝试了一个MyVector
类,而不是 std::string)
根据 C++11 标准中的定义,
是否
getName()
返回右值?在上面的第 5 行中,调用了哪个字符串的构造函数(移动或复制)?我是否必须调用
std::move()
移动构造函数来调用?使用移动语义,它是否比编译器提供的“复制省略”优化效率低?