Rvalue引用和Move语义是一个主要的C++ 11特性,它可以通过减少不必要的副本来显着加速代码.当使用c ++ 11/0x编译器时(例如gcc 4.6),STL已更新为使用此新功能
Boost 1.48引入了一个新的库,以便在旧的C++ 03编译器上模拟移动语义.这个库通过引入宏来扩展为真正的右值引用,当使用C++ 11编译器编译代码或使用C++ 03编译器编译代码时模拟rvalue引用.
除了boost::container更新任何其他的boost库以利用移动语义之外呢?
是否有一个路线图详细说明何时/如果将移动语义添加到其他boost库?
boost::multi_index_container已经提到在Boost.MultiIndex Future工作中添加了移动语义
,因为它是在1.31版本中引入的.
下面的代码编译并运行得很好.正当我以为我开始对rvalue引用和std :: forward进行了很好的掌握 - 这个非常简单的代码揭示了rvalue有一些非常基本的东西,我不明白.请澄清.
#include <iostream>
#include <iomanip>
using namespace std;
void fn( int&& n )
{
cout << "n=" << n << endl;
n = 43;
cout << "n=" << n << endl;
}
int main( )
{
fn( 42 );
}
Run Code Online (Sandbox Code Playgroud)
我用g ++ 4.7使用以下命令行编译它:
g ++ --std = c ++ 11 test.cpp
输出为:
n = 42
n = 43
我的主要问题是编译器在函数fn中存储'n'的位置?
我正在使用C++编写一个小型数值分析库.我一直在尝试使用最新的C++ 11功能实现,包括移动语义.我理解以下帖子中的讨论和最佳答案:C++ 11 rvalues和移动语义混淆(return语句),但有一种情况我仍然试图包围我的头脑.
我有一个类,称之为T,它配备了重载运算符.我也有复制和移动构造函数.
T (const T &) { /*initialization via copy*/; }
T (T &&) { /*initialization via move*/; }
Run Code Online (Sandbox Code Playgroud)
我的客户端代码大量使用运算符,所以我试图确保复杂的算术表达式从移动语义中获得最大的好处.考虑以下:
T a, b, c, d, e;
T f = a + b * c - d / e;
Run Code Online (Sandbox Code Playgroud)
没有移动语义,我的操作符每次都使用复制构造函数创建一个新的局部变量,所以总共有4个副本.我希望通过移动语义,我可以将其减少到2个副本加上一些动作.在括号中:
T f = a + (b * c) - (d / e);
Run Code Online (Sandbox Code Playgroud)
每个(b * c)并且(d / e)必须以通常的方式创建临时副本,但是如果我可以利用其中一个临时工具仅用移动来累积剩余的结果,那将是很好的.
使用g ++编译器,我已经能够做到这一点,但我怀疑我的技术可能不安全,我想完全理解为什么.
以下是加法运算符的示例实现:
T operator+ (T const& x) const
{
T result(*this);
// …Run Code Online (Sandbox Code Playgroud) 该程序试图将一个字符串移出一个函数并用它来构造另一个字符串:
#include <iostream>
#include <string>
#include <utility>
std::string && Get_String(void);
int main(){
std::string str{Get_String()};
std::cout << str << std::endl;
return 0;
}
std::string && Get_String(void){
std::string str{"hello world"};
return std::move(str);
}
Run Code Online (Sandbox Code Playgroud)
程序编译,但执行时会出现段错误.
这是我的理由: Get_String将创建一个本地字符串.在字符串超出范围之前,需要创建并返回该字符串的副本.该副本将用于在main中构造字符串.但是,如果我将字符串移出函数,则不需要复制.
为了理解移动语义,有人可以解释为什么我在做什么,可能没有任何意义.是否可以将对象移出函数?
编辑:
如果我更改函数签名,它编译并正确运行:
std::string && Get_String(void);
Run Code Online (Sandbox Code Playgroud)
至
std::string Get_String(void);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,在返回期间移动字符串是否仍然更有效?
像这样的代码经常出现在r值引用文章中:
void g(X);
void f()
{
X b;
g(b); // still need the value of b
…
g( std::move(b) ); // all done with b now; grant permission to move
}
Run Code Online (Sandbox Code Playgroud)
编译器是否可以自动生成此优化,即检测l值是否会被破坏并且可能会被移除,或者这会违反标准,假设一般情况编译器不知道如何是移动,复制或破坏为X类实现?
如果允许这样的优化,它是否由某些编译器在实践中执行?
在Scott Meyer的新书中,他提出了rvalue引用限定符的示例用法,如下所示:
class Widget {
private:
DataType values;
public:
DataType& data() & { return values; }
DataType data() && { return std::move(values); } // why DataType?
};
Run Code Online (Sandbox Code Playgroud)
以便:
auto values = makeWidget().data();
Run Code Online (Sandbox Code Playgroud)
移动构造values而不是复制构造它.
为什么rvalue-ref-qualified data()返回DataType而不是DataType&&?在这种情况下auto仍会推断DataType(虽然decltype(auto)不会 - 但这不是唯一的理由,更喜欢返回一个值而不是ravlue ref).这个高度投票的答案会返回一个rvalue ref,这对我来说在概念上更有意义.
我对以下代码感到困惑:
struct test {
void f() & {
std::cout << "&" << std::endl;
}
void f() const& {
std::cout << "const&" << std::endl;
}
void f() && {
std::cout << "&&" << std::endl;
}
void f() const&& {
std::cout << "const&&" << std::endl;
}
void g() & {
std::cout << "& -> ";
f();
}
void g() const& {
std::cout << "const& -> " ;
f();
}
void g() && {
std::cout << "&& -> ";
f();
}
void g() …Run Code Online (Sandbox Code Playgroud) 在创建对象时使用r值引用是否有任何优势,否则它将在正常的局部变量中?
Foo&& cn = Foo();
cn.m_flag = 1;
bar.m_foo = std::move(cn);
//cn is not used again
Foo cn;
cn.m_flag = 1;
bar.m_foo = std::move(cn); //Is it ok to move a non rvalue reference?
//cn is not used again
Run Code Online (Sandbox Code Playgroud)
在第一个代码片段中,似乎很明显没有任何副本,但我猜在第二个编译会优化副本出来?
同样在第一个片段中,对象实际存储在内存中(第二个是存储在封闭函数的堆栈帧中)?
我想说明我的类的构造函数A将取得传递Data参数的所有权.显而易见的事情是采用一个unique_ptr值:
class A
{
public:
A(std::unique_ptr<Data> data) : _data(std::move(data)) { }
std::unique_ptr<Data> _data;
};
Run Code Online (Sandbox Code Playgroud)
但是,对于我的用例,没有理由为什么Data应该是指针,因为值类型就足够了.我能想到的唯一剩下的选项,以使真正明确表示Data会为所拥有的A是路过的右值引用:
class A
{
public:
A(Data&& data) : _data(std::move(data)) { }
Data _data;
};
Run Code Online (Sandbox Code Playgroud)
这是一种表明所有权的有效方式,还是有更好的方法可以不使用unique_ptr?
说我有以下功能
void doWork(Widget && param) // param is an LVALUE of RRef type
{
Widget store = std::move(param);
}
Run Code Online (Sandbox Code Playgroud)
为什么我需要param回到rvalue std::move()?是不是很明显,paramrvalue 的类型是因为它在函数签名中被声明为右值引用?不应该仅仅根据这个原则自动调用移动构造函数吗?
为什么不默认发生这种情况?
c++ rvalue-reference move-constructor lvalue-to-rvalue stdmove