问题标签 [rvalue-reference]
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++ - 标准库容器在 GCC 中生成大量右值副本
我正在为 linux 和 windows 编写一个应用程序,并注意到 GCC 构建对复制构造函数产生了很多无用的调用。
这是产生此行为的示例代码:
此测试仅创建一个包含 3 个元素的向量。我期望 3 个默认构造函数调用和 0 个副本,因为没有A
左值。
在 Visual C++ 2010 中,输出为:
在 GCC 4.4.0 (MinGW) 中,(-O2 -std=c++0x),输出为:
发生了什么事,我该如何解决?实际课程的副本很昂贵,默认构造和移动很便宜。
c++ - 通过 std::bind 传递右值
我想将一个右值传递std::bind
给一个在 C++0x 中采用右值引用的函数。我不知道该怎么做。例如:
c++ - 对 const 的右值引用有什么用吗?
我猜不是,但我想确认一下。有什么用const Foo&&
,Foo
类类型在哪里?
c++ - C++ - 具有右值引用的函数模板特化的行为
我正在尝试实现条件指针取消引用功能。基本思路如下:
为了限制必要专业化的数量,我尝试在arg
不是指针的情况下使用右值引用。这是我当前的实现(std::cout
仅用于调试目的):
现在,我在 GCC 4.6 下得到了一个相当奇怪的行为。第一个重载用于非指针类型和指针类型。显然,当使用指针类型时,它与第二个重载冲突。如果我注释掉第二个并使用第一个调用以下...
...相应的控制台输出为:
在同一上下文中,非指针类型(根据std::is_pointer
)怎么可能也是指针类型(根据)?typeid
由于std::is_pointer
错误地报告p
为非指针类型,两个重载之间会出现冲突。此外,当我在第一次重载中将 r 值引用替换为标准引用时:
它不再与第二次重载冲突......我只是不明白发生了什么。顺便说一句,使用第二个重载会产生(正如预期的那样):
谢谢你的帮助。
c++ - C++11 右值和移动语义混淆(return 语句)
我试图理解右值引用并移动 C++11 的语义。
这些示例之间有什么区别,其中哪些不进行矢量复制?
第一个例子
第二个例子
第三个例子
c++ - std::string 可以为右值 *this 重载“substr”并窃取资源吗?
我突然想到std::string
,substr
当它可以从*this
.
N3225 的标准库包含以下成员函数声明std::string
可以实现为右值优化的实现是否可以substr
重载并提供两个版本,其中一个可以为右值字符串重用缓冲区?
我想右值版本可以按如下方式实现,*this
将设置的内存重用*this
到移动状态。
这在常见的字符串实现上是否以有效的方式工作,还是需要太多的内务处理?
c++ - Visual C++ 2010,右值引用错误?
它是 Visual C++ 2010 中的错误还是正确的行为?
我想,函数 f(T &&) 永远不应该被调用,而是用 T = int & 调用。输出:
更新 1你知道任何 C++x0 编译器作为参考吗?我已经尝试过 comeau 在线试驾,但无法编译 r 值参考。
更新 2解决方法(使用 SFINAE):
更新 3即使没有函数模板实例化,一些编译器也会在 static_assert(false, "no way") 上触发。解决方法(感谢@Johannes Schaub - litb)
或者
c++11 - 如何在具有右值的算术表达式中实现“最佳”运算符重载分辨率?
首先,我为这个过于冗长的问题道歉。我想不出任何其他方法来准确总结我的问题......现在进入实际问题:
我目前正在尝试使用 C++0x 右值引用...以下代码会产生不需要的行为:
结果输出
构造新的临时对象来存储结果
构造新的临时对象来存储结果
重用临时的第一个操作数来存储结果
重用临时的第一个操作数来存储结果
虽然我曾希望像
构造新的临时
操作数来存储结果 重用临时的第一个操作数来存储结果
重用临时的第二个操作数来存储结果
重用临时的第二个操作数来存储结果
在尝试重新制定编译器正在执行的操作之后(我正在使用带有选项 -std=c++0x 的 MinGW G++ 4.5.2 以防万一),它实际上看起来很合乎逻辑。该标准说,相等优先级的算术运算从左到右进行评估/分组(为什么我假设从右到左我不知道,我想这对我来说更直观)。所以这里发生的事情是编译器首先评估子表达式(v3 + v4)
(因为它在括号中?),然后开始从左到右将表达式中的操作与运算符重载进行匹配,导致对子表达式的Vector4 operator + (const Vector4& other)
调用表达v1 + v2
. 如果我想避免不必要的临时性,我必须确保不超过一个左值操作数出现在任何带括号的子表达式的紧靠左侧,这对于使用这个“库”并且无辜地期待的任何人来说都是违反直觉的最佳性能(如最小化临时创建)。
(我知道我的代码中关于何时添加到 的结果中存在歧义operator + (Vector4&& v1, const Vector4& v2)
,从而导致警告。但在我的情况下它是无害的,我不想为两个右值引用操作数添加另一个重载- 有人知道是否有办法在 gcc 中禁用此警告?)operator + (Vector4&& other)
(v3 + v4)
v1 + v2
长话短说,我的问题归结为:是否有任何方式或模式(最好是独立于编译器)这个向量类可以被重写以允许在表达式中任意使用括号,这仍然会导致运算符重载的“最佳”选择(最佳就“性能”而言,即最大化与右值引用的绑定)?也许我要求太多了,这是不可能的……如果是这样,那也没关系。我只是想确保我没有遗漏任何东西。
提前谢谢了
附录
首先感谢我在几分钟内得到的快速回复(!) - 我真的应该早点开始在这里发帖......
在评论中回复变得乏味,所以我认为澄清我对这个类设计的意图是有序的。如果有的话,也许你可以指出我思维过程中的一个基本概念缺陷。
您可能会注意到我在类中没有任何资源,例如堆内存。它的成员甚至只是标量类型。乍一看,这使它成为基于移动语义的优化的可疑候选者(另请参阅这个问题,它实际上帮助我很好地掌握了右值引用背后的概念)。
然而,由于这个类应该是一个原型的类将在性能关键的上下文中使用(准确地说是 3D 引擎),所以我想优化每一个可能的小事情。低复杂度算法和与数学相关的技术(如查找表)当然应该构成大部分优化,因为其他任何东西都只是解决症状而不是消除性能不佳的真正原因。我很清楚这一点。
顺便说一句,我的意图是使用向量和矩阵优化代数表达式,这些向量和矩阵本质上是普通的旧数据结构,其中没有指向数据的指针(主要是由于堆上的数据存在性能缺陷[有取消引用其他指针、缓存注意事项等])。
我不关心移动赋值或构造,我只是不希望在评估复杂代数表达式期间创建比绝对必要的更多临时变量(通常只有一个或两个,例如矩阵和向量)。
这些是我的想法,可能是错误的。如果是,请纠正我:
- 要在不依赖 RVO 的情况下实现这一点,必须通过引用返回(再次提醒:请记住,我没有远程资源,只有标量数据成员)。
- 通过引用返回使函数调用表达式成为左值,暗示返回的对象不是临时对象,这是不好的,但通过右值引用返回使函数调用表达式成为 xvalue(见 3.10.1),这在我的方法的背景(见 4)
- 通过引用返回是危险的,因为对象的生命周期可能很短,但是:
- 临时对象可以保证在创建它们的表达式的计算结束之前一直存在,因此:
- 如果该右值引用参数所引用的对象是通过引用返回的对象,则使从那些将至少一个右值引用作为其参数的运算符通过引用返回是安全的。所以:
- 任何仅使用二元运算符的任意表达式都可以通过在涉及不超过一种类似 PoD 的类型时仅创建一个临时值来评估,并且二元运算本质上不需要临时值(如矩阵乘法)
(通过右值引用返回的另一个原因是,就函数调用表达式的右值而言,它的行为类似于按值返回;并且运算符/函数调用表达式必须是右值才能绑定到随后调用采用右值引用的运算符。如 (2) 中所述,对通过引用返回的函数的调用是左值,因此将绑定到具有签名的运算符T operator+(const T&, const T&)
,从而导致创建不必要的临时)
我可以通过使用 C 风格的函数方法来实现所需的性能add(Vector4 *result, Vector4 *v1, Vector4 *v2)
,但是来吧,我们生活在 21 世纪......
总之,我的目标是创建一个向量类,它使用重载运算符实现与 C 方法相同的性能。如果这本身是不可能的,那我想也无济于事。但如果有人能向我解释为什么我的方法注定要失败,我将不胜感激(当然,从左到右的操作员评估问题是我发表帖子的最初原因)。
事实上,我一直在使用“真正的”矢量类,这是一个简化了一段时间,到目前为止没有任何崩溃或损坏的内存。事实上,我从来没有真正返回本地对象作为引用,所以不应该有任何问题。我敢说我所做的是符合标准的。
当然,对原始问题的任何帮助也将不胜感激!
非常感谢所有的耐心再次
c++ - 右值引用是否有reference_wrapper<>?
我想知道如何执行以下操作
如何传递右值引用并将其作为右值引用(可能已包装)存储在调用包装器中?我知道我可以手动编写一个std::reference_wrapper<>
具有转换功能的类T&&
,但我宁愿避免这种情况并使用标准技术。
我按照 AProgrammer 的建议实现了它:
现在我可以说
如果我们将左值传递给,它会将其作为引用输入参数的左值转发,因此在这种情况下make_adv
,它可以用作 的替代品。std::ref
c++ - 类、右值和右值引用
左值是绑定到内存的确定区域的值,而右值是一个表达式值,其存在是暂时的,不一定指向内存的确定区域。每当在需要右值的位置使用左值时,编译器都会执行左值到右值的转换,然后继续求值。
http://www.eetimes.com/discussion/programming-pointers/4023341/Lvalues-and-Rvalues
每当我们构造一个临时(匿名)类对象或从函数返回一个临时类对象时,虽然该对象是临时的,但它是可寻址的。但是,该对象仍然是有效的右值。这意味着对象是 a) 可寻址右值或 b) 当编译器期望使用左值时,它正在从左值隐式转换为右值。
例如:
我们还知道,函数返回的临时对象(在以下情况下a
)是左值,如下代码段:
产生以下输出:
int conversion ctor
lvalue copy ctor
表示ret_a
使用实参A(5)
调用函数调用转换构造函数A::A(int)
,该构造函数构造函数的形式参数a
,值为 5。
当函数完成执行时,它会构造一个临时A
对象,使用a
它作为参数,调用A::A(A&)
. 但是,如果我们A::A(A&)
要从重载构造函数列表中删除,返回的临时对象仍然会匹配右值引用构造函数A::A(A&&)
。
这是我不太理解的:对象如何同时a
匹配右值引用和左值引用?很明显,这A::A(A&)
是比A::A(A&&)
(因此a
必须是左值)更好的匹配。但是,由于不能将右值引用初始化为左值,鉴于形式参数a
是左值,它不应该能够匹配对A::A(A&&)
. 如果编译器正在进行左值到右值的转换,那将是微不足道的。A::A(A&)
事实上,从 'A' 到 'A&' 的转换也是微不足道的,两个函数应该具有相同的隐式转换序列等级,因此,当两者A::A(A&&)
都在重载函数中时,编译器不应该能够推断出最佳匹配函数候选集。
此外,问题(我之前问过的)是:
给定对象如何同时匹配右值引用和左值引用?