前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >带着问题去学习(1)-右值引用与智能指针

带着问题去学习(1)-右值引用与智能指针

作者头像
程序员小王
发布2022-01-17 17:12:51
6830
发布2022-01-17 17:12:51
举报
文章被收录于专栏:架构说

https://github.com/watchpoints/daily-interview/issues/25

右值引用解决了什么问题,他出现的目的是什么?

  • Perhaps the most significant new feature in C++11 is rvalue references;

they’re the foundation on which move semantics and perfect forwarding are built.

https://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers

右值引用是将这两个完全不同的特征联系在一起的粘合剂。

它是使移动语义和完美转发成为可能的底层语言机制。

  • Rvalue references are the glue that ties these two rather disparate features together.
  • They’re the underlying language mechanism that makes both move semantics and perfect forwarding possible.

我不会直接解释什么是右值引用。

相反,

我将从要解决的问题开始, 然后展示右值引用如何提供解决方案。

这样,右值引用的定义对您来说就会显得合理和自然。

右值引用至少解决了两个问题:

  • 实现移动语义
  • 完美转发

I will not jump right in and explain what rvalue references are. Instead, I will start with the problems that are to be solved and then show how rvalue references provide the solution.

Rvalue references solve at least two problems:

  • Implementing move semantics
  • Perfect forwarding

画外音:

您将了解 std::move 和 std::forward 的使用约定。你会对“type&&”的含糊不清的性质感到舒服,

type&& 本质是什么,回答到问题,右值引用是什么?

第一次听 这个概念,感到 疑惑地方

疑惑 1 为什么说

The construct “type&&” doesn’t always represent an rvalue reference.

  • The construct “type&&” doesn’t always represent an rvalue reference.
  • Rvalue references allow a function to branch at compile time
  • move 就是swap吗?

疑惑2:the parameter w is an lvalue

the parameter w is an lvalue

  • Is an Rvalue Reference an Rvalue?

void f(Widget&& w); the parameter w is an lvalue, even though its type is rvalue-reference-to-Widget

It’s especially important to remember this when dealing with a parameter of rvalue reference type, because the parameter itself is an lvalue:

  1. && 这是个语法错误吗?

c++能定义引用的引用吗?答案是:不能。

不过你可以补充说:不过有两个例外:类型别名和模板参数时可以间接定义引用的引用。https://www.zhihu.com/question/28023545

代码语言:javascript
复制
c++11支持reference collapse,就是:

& &=>&
&& & =>&
& &&=>&
&& &&=>&&

画外音:

正确的说法是“引用折叠”而其实引用折叠后依旧是普通的引用或者右值引用,

所以其实“引用的引用”严格来说是不存在的。

c++需要引用折叠的原因是为了实现std::move。也就是说,

所谓“引用的引用”的存在价值,只是为std::move、std::forward等而服务的,

小思考:

引用就是指针,二级指针 二级引用 可以等价理解吗?

Effective Modern C++, Chapter 5, Item 28: Understand reference collapsingYou are forbidden from declaring references to references, but compilers may produce them inparticular contexts.

关键点3

You might expect T&& to only bind to rvalues, because at first glance, it looks like an rvalue reference.

As it turns out though, T&& also binds to lvalues:

代码语言:javascript
复制
template<typename T>
void foo(T&& param)
{
    cout<< param <<endl;
}
void tet_foo()
{  
    int a=27;
    foo(a) ; // x is lvalue, so T is int&  param's type is also int&
    foo(27); // 27 is rvalue, so T is int  param's type is therefore int&&
}

画外音:类型推导功能

Here, the following apply:

  • When foo is called on an lvalue of type A, then T resolves to A& and hence, by the reference collapsing rules above, the argument type effectively becomes A&.
  • When foo is called on an rvalue of type A, then T resolves to A, and hence the argument type becomes A&&.

Item 24: Distinguish universal references from rvalue references

带着问题去学习:明确自己想解决什么问题

  • 小王提问1:The other meaning for “T&&” is either rvalue reference or lvalue reference
  • 小王提问2:为什么说vector push_back 函数 不会发生类型推导,emplace_back

结论是什么

Item 25: Use std::move on rvalue references, std::forward on universal references

带着问题去学习:明确自己想解决什么问题

  • 使用场景是什么?

结论是什么

带着问题去学习智能指针

问题是什么?明确 不同平台怎么实现

这里讨论不是智能指针是如何实现和设计的,讨论是如何使用的 make_unique从这里开始

//提问1. unique_ptr能不能相互赋值, //提问2. unique_ptr 如何解决?//提问3。unique_ptr 有什么后果

代码语言:javascript
复制
  std::unique_ptr<int> foo ;
  std::unique_ptr<int> bar;
  
  //bar = foo; 
  // unique_ptr& operator=(const unique_ptr&) = delete;
  
  
  //为什么这个成立呢
  foo = std::unique_ptr<int>(new int (101));  // rvalue
  //为什么这个成立呢
  bar = std::move(foo);                       // using std::move
  
  //为什么这个成立呢
  std::unique_ptr<int> up3 = std::make_unique<int>(3);

结论是什么

代码语言:javascript
复制
// This has been tested with:
// - MSVC 11.0 (Visual Studio 2012)
// - gcc 4.6.3
// - Xcode 4.4 (with clang "4.0")
  • 青铜(小白)理解:这有什么呀?make_unique 创造 和智能指针关系不太大
  • 白银(初级)理解:
MSVC 11.0 (Visual Studio 2012)实现
  • https://github.com/watchpoints/microsoft_STL
代码语言:javascript
复制
template <class _Ty, class... _Types, enable_if_t<!is_array_v<_Ty>, int> = 0>
_NODISCARD unique_ptr<_Ty> make_unique(_Types&&... _Args) { // make a unique_ptr
    return unique_ptr<_Ty>(new _Ty(_STD forward<_Types>(_Args)...));
}
gcc 实现
  • https://github.com/watchpoints/gcc/blob/master/libstdc%2B%2B-v3/include/bits/unique_ptr.h
代码语言:javascript
复制
 /// std::make_unique for single objects
  template<typename _Tp, typename... _Args>
    inline typename _MakeUniq<_Tp>::__single_object
    make_unique(_Args&&... __args)
    { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); 

更多阅读

  • https://en.cppreference.com/w/cpp/language/static_cast 第二 第三点
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-12-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Offer多多 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 右值引用解决了什么问题,他出现的目的是什么?
  • 第一次听 这个概念,感到 疑惑地方
    • 疑惑 1 为什么说
      • 疑惑2:the parameter w is an lvalue
        • 关键点3
        • Item 24: Distinguish universal references from rvalue references
          • 带着问题去学习:明确自己想解决什么问题
            • 结论是什么
            • Item 25: Use std::move on rvalue references, std::forward on universal references
              • 带着问题去学习:明确自己想解决什么问题
                • 结论是什么
                • 带着问题去学习智能指针
                  • 问题是什么?明确 不同平台怎么实现
                    • 结论是什么
                    • 更多阅读
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档