右值引用

左值和右值

(1)两者区别:

  ①左值:能对表达式取地址、或具名对象/变量。一般指表达式结束后依然存在的持久对象。

  ②右值:不能对表达式取地址,或匿名对象。一般指表达式结束就不再存在的临时对象。

总结:一般而言,一个左值表达式表示的是一个对象的身份,而一个右值表达式表示的是对象的值。 

(2)右值的分类

  ①将亡值(xvalue,eXpiring value):指生命期即将结束的值,一般是跟右值引用相关的表达式,这样表达式通常是将要被移动的对象,如返回类型为T&&的函数返回值(如std::move)、经类型转换为右值引用的对象(如static_cast<T&&>(obj))、xvalue类对象的成员访问表达式也是一个xvalue(如Test().memberdata,注意Test()是个临时对象)

  ②纯右值(prvalue, PureRvalue):按值返回的临时对象运算表达式产生的临时变对象原始字面量lambda表达式等。

(3)C++11中的表达式

【C++ Primer 第13章】6.对象移动

  

标准库的 move 函数

• 虽然不能将一个右值直接绑定到一个左值上,但可以显式地将一个左值转换为对应的右值引用类型。我们可以通过调用一个名为 move的新标准库函数来获得绑定到左值上的引用。头文件utility。

int &&rr3 = std::move(rr1); //ok

• 我们可以销毁一个移后源对象,也可以赋予它新值,但不能使用一个移后源对象的值。

 移动构造函数和移动赋值运算符

与拷贝函数不同,移动构函数不分配任何新的内存,它接管给定StrVec中的内存,在接管内存之后, 它将给的对象中的指针置为nullptr,这样就完成了从给定对象的移动操作,此对象将继续存在。

  1 #include<iostream>
  2 #include<string>
  3 #include<memory>
  4 using namespace std;
  5 
  6 class StrVec {
  7 public:
  8     StrVec(): elements(nullptr), first_free(nullptr), cap(nullptr) {}
  9     StrVec(const StrVec &);
 10     StrVec& operator=(const StrVec&);
 11     ~StrVec() { free(); };
 12 
 13     StrVec(StrVec &&s) noexcept;
 14     StrVec& opearator=(StrVec &&rhs) noexcept;
 15 
 16     void push_back (const string&);
 17     size_t size() const       { return first_free - elements; }
 18     size_t capacity() const   { return cap - elements; }
 19     string *begin() const     { return elements; }
 20     string *end() const       { return first_free; }
 21 
 22 private:
 23     static allocator<string> alloc;
 24     void chk_n_alloc() { if (size() == capacity()) reallocate(); }
 25     pair<string*, string*> alloc_n_copy(const string*, const string *);
 26     void free();
 27     void reallocate();
 28     string *elements;    //指向数组首元素的指针
 29     string *first_free;  //指向数组第一个空闲元素的指针
 30     string *cap;         //指向数组尾后位置的指针
 31 };
 32 
 33 StrVec::StrVec(const StrVec &s)
 34 {
 35     auto newdata = alloc_n_copy(s.begin(), s.end());
 36     elements = newdata.first;
 37     first_free = cap = newdata.second;
 38 }
 39 
 40 StrVec& StrVec::operator=(const StrVec &rhs)
 41 {
 42     auto data = alloc_n_copy(rhs.begin(), rhs.end());
 43     free();
 44     elements = data.first;
 45     first_free = cap = newdata.second;
 46     return *this;
 47 }
 48 
 49 void StrVec::free()
 50 {
 51     if (elements)
 52     {
 53         for (auto p = first_free; p != elements; )
 54             alloc.destroy(--p);
 55         alloc.deallocate(elements, cap - elements);
 56     }
 57 }
 58 
 59 pair<string *, string *> StrVec::alloc_n_copy(const string *b, const string *e)
 60 {
 61     auto data = alloc.allocate(e - b);
 62     return { data, uninitialized_copy(b, e, data) };
 63 }
 64 
 65 void StrVec::push_back(const string& s)
 66 {
 67     chk_n_alloc();
 68     alloc.construct(first_free++, s);
 69 }
 70 
 71 void StrVec::reallocate()
 72 {
 73     auto newcapacity = size() ? 2 * size() : 1;
 74     auto newdata = alloc.allocate(newcapacity);
 75     auto dest = newdata;
 76     auto elem = elements;  //原对象的elements指针
 77     for (size_t i = 0; i != size(); ++i)
 78         alloc.construct(dest++, std::move(*elem++));
 79     free();
 80     elements = newdata;
 81     first_free = dest;
 82     cap = elements + newcapacity;
 83 }
 84 
 85 StrVec::StrVec(StrVec &&s) noexcept
 86 : elements(s.elements), first_free(s.first_free), cap(s.cap)
 87 {
 88     s.elements = s.first_free = cap = nulllptr;
 89 }
 90 
 91 StrVec& StrVec::StrVec(StrVec &&s) noexcept
 92 {
 93     if (this = &s)
 94     {
 95         free();
 96         elemens = rhs.elements;
 97         first_free = .frhsirst_free;
 98         cap = rhs.cap;
 99         rhs.elements = srhs.first_free = rhs.cap = nullptr;
100     }
101     return *this;
102 }
View Code

相关文章:

  • 2022-12-23
  • 2022-12-23
  • 2022-02-06
  • 2022-12-23
  • 2022-12-23
  • 2021-06-06
  • 2021-06-25
  • 2021-06-23
猜你喜欢
  • 2021-06-21
  • 2021-11-24
  • 2022-02-06
  • 2021-10-04
  • 2021-11-05
  • 2022-12-23
  • 2021-11-03
相关资源
相似解决方案