2.1 Rvalue References

1. Rvalue References

std::string returnStringByValue(); // forward declaration
...
std::string s{"hello"};
...
std::string&& r1{std::move(s)}; // OK

std::string&& r2{returnStringByValue()}; 
// OK, extends lifetime of return value

std::string&& r3{s}; // ERROR

①右值引用必须引用一个现存的对象,现存的对象必须作为初始值传递,
但是,根据移动语意的规则,它们只能引用一个没有名称的临时对象或标记为std::move()的对象
std::string&& r3{s}; // ERROR
③没有名称的临时对象和被move标记的对象,我们称之为右值
这些对象只能引用 右值

2. 如何初始化右值引用

std::string s{"hello"};
...
std::string&& r1{std::move(s)}; // OK, reference to s

std::string&& r2 = std::move(s); // OK, reference to s

std::string&& r3(std::move(s)); // OK, reference to s

3.右值引用作为形参

①这个形参 只能被临时对象或者被move标记的对象绑定
②你可以随意修改这个对象
③调用该函数的人,表示该对象的值已经没用了,但是该对象还是可以使用
④任何修改都应该保持被引用的对象处于有用的状态

void foo(std::string&& rv); 
// takes only objects where we no longer need the value
...
std::string s{"hello"};
...
foo(s); // ERROR

foo(std::move(s)); // OK, value of s might change

foo(returnStringByValue()); // OK

⑤一个对象std::move(),作为实参被传入以后,就不该在被使用了
该对象仍是可以使用的

void foo(std::string&& rv);
 // takes only objects where we no longer need the value
...
std::string s{"hello"};
...
foo(std::move(s)); // OK, value of s might change

std::cout << s << \n; 
// OOPS, you don’t know which value is printed

foo(std::move(s)); // OOPS, you don’t know which value is passed
s = "hello again"; // OK, but rarely done
foo(std::move(s)); // OK, value of s might change
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
右值引用(rvalue references)是C++11引入的一种新的引用类型,用于表示一个临时对象或将要被销毁的对象。与左值引用(lvalue references)不同,右值引用只能绑定到右值(包括临时对象和将要被销毁的对象),不能绑定到左值(即不能绑定到具有名称的对象)。 右值引用使用&&符号表示,语法格式如下: ```c++ T&& var; ``` 其中,`T`表示要引用的类型,`var`表示引用的变量名。 右值引用可以用于实现移动语义(move semantics),通过将一个对象的资源(如内存、文件句柄等)从源对象转移到目标对象,避免了不必要的复制和内存分配,提高了程序的效率。 例如,我们可以定义一个带有移动构造函数的类`MyString`: ```c++ #include <iostream> #include <cstring> class MyString { public: // 默认构造函数 MyString() : m_data(nullptr), m_length(0) {} // 带参构造函数 MyString(const char* str) : m_data(nullptr), m_length(0) { if (str == nullptr) { return; } m_length = strlen(str); m_data = new char[m_length + 1]; strncpy(m_data, str, m_length); m_data[m_length] = '\0'; } // 移动构造函数 MyString(MyString&& other) : m_data(other.m_data), m_length(other.m_length) { other.m_data = nullptr; other.m_length = 0; } // 析构函数 ~MyString() { if (m_data != nullptr) { delete[] m_data; m_data = nullptr; } } // 输出字符串 void print() const { if (m_data != nullptr) { std::cout << m_data; } else { std::cout << "null"; } } private: char* m_data; // 字符串数据 int m_length; // 字符串长度 }; ``` 在该类中,我们定义了一个移动构造函数`MyString(MyString&& other)`,该函数接受一个右值引用作为参数,将源对象的资源转移给目标对象,并将源对象的指针设置为`nullptr`,以防止资源被重复释放。 然后,我们可以使用如下方式创建一个临时对象并将其转移给另一个对象: ```c++ int main() { MyString str1("hello"); // 调用带参构造函数 MyString str2(std::move(str1)); // 调用移动构造函数 str1.print(); // 输出null str2.print(); // 输出hello return 0; } ``` 在上面的代码中,我们首先创建了一个`MyString`对象`str1`,然后将其移动给另一个对象`str2`,最后输出两个对象的值。可以看到,源对象`str1`的值变成了`null`,目标对象`str2`的值变成了`hello`,说明移动构造函数成功地将源对象的资源转移给了目标对象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值