当前位置: 首页 > news >正文

手机网站可以做公众号微信建设银行官方网站

手机网站可以做公众号,微信建设银行官方网站,福建网站建设费用,杭州好的做网站公司背景: 最近看了候捷老师的c的教程, 他说移动构造方法要加noexcept, 在vector扩容的时候, 如果有移动构造方法没有加noexcept,是不会调用的. 个人感觉有些神奇, 这就去查下一探究竟. 过程: 测试代码如下: #include <iostream> #include <vector> struct A {A(){s…

背景:

最近看了候捷老师的c++的教程, 他说移动构造方法要加noexcept,  在vector扩容的时候, 如果有移动构造方法没有加noexcept,是不会调用的. 个人感觉有些神奇, 这就去查下一探究竟.

过程:

测试代码如下:

#include <iostream>
#include <vector>
struct A
{A(){std::cout<<"A::A()"<<std::endl;}A(const A &a){std::cout<<"A::A(const A&a)"<<std::endl;}A(A &&a) {std::cout<<"A::A(A &&a)"<<std::endl;}A& operator=(const A&a) {std::cout<<"operator=(const A&a)"<<std::endl;return *this;}A& operator = (A &&a){std::cout<<"operator =(A&&a)"<<std::endl;return *this;}
};
int main()
{std::vector<A> vecA;A a;vecA.push_back(a);std::cout<<"1"<<std::endl;vecA.push_back(a);std::cout<<"2"<<std::endl;vecA.push_back(a);std::cout<<"3"<<std::endl;vecA.push_back(a);std::cout<<"4"<<std::endl;return 0;}

 执行结果如下:

A::A()
A::A(const A&a)
1
A::A(const A&a)
A::A(const A&a)
2
A::A(const A&a)
A::A(const A&a)
A::A(const A&a)
3
A::A(const A&a)
4

我们知道vector 是要扩容的, 在A(A &&a) 并没有添加noexcept关键字, 所以扩容的时候,使用的也是拷贝构造方法, 那接下来我们看下加下 noexcept 后了,结果是什么样的

#include <iostream>
#include <vector>
struct A
{A(){std::cout<<"A::A()"<<std::endl;}A(const A &a){std::cout<<"A::A(const A&a)"<<std::endl;}A(A &&a) noexcept{std::cout<<"A::A(A &&a)"<<std::endl;}A& operator=(const A&a) noexcept{std::cout<<"operator=(const A&a)"<<std::endl;return *this;}A& operator = (A &&a){std::cout<<"operator =(A&&a)"<<std::endl;return *this;}
};
int main()
{std::vector<A> vecA;A a;vecA.push_back(a);std::cout<<"1"<<std::endl;vecA.push_back(a);std::cout<<"2"<<std::endl;vecA.push_back(a);std::cout<<"3"<<std::endl;vecA.push_back(a);std::cout<<"4"<<std::endl;return 0;}

执行结果如下:

A::A()
A::A(const A&a)
1
A::A(const A&a)
A::A(A &&a)
2
A::A(const A&a)
A::A(A &&a)
A::A(A &&a)
3
A::A(const A&a)
4

在A(A &&a) noexcept 后, 调用的方法就是移动构造方法, 感觉挺不可思议的, 带着这个疑问,我们看下std::vector 源码来找寻答案

揭秘:

push_back 源码如下:

template <class _Tp, class _Allocator>
inline _LIBCPP_INLINE_VISIBILITY
void
vector<_Tp, _Allocator>::push_back(const_reference __x)
{if (this->__end_ != this->__end_cap()){__RAII_IncreaseAnnotator __annotator(*this);__alloc_traits::construct(this->__alloc(),_VSTD::__to_raw_pointer(this->__end_), __x);__annotator.__done();++this->__end_;}else__push_back_slow_path(__x);
}

因为我们要看扩容相关的代码,  __push_back_slow_path(__x); 对应的需要扩容要调用的代码

#ifndef _LIBCPP_CXX03_LANG
vector<_Tp, _Allocator>::__push_back_slow_path(_Up&& __x)
#else
vector<_Tp, _Allocator>::__push_back_slow_path(_Up& __x)
#endif
{allocator_type& __a = this->__alloc();__split_buffer<value_type, allocator_type&> __v(__recommend(size() + 1), size(), __a);// __v.push_back(_VSTD::forward<_Up>(__x));__alloc_traits::construct(__a, _VSTD::__to_raw_pointer(__v.__end_), _VSTD::forward<_Up>(__x));__v.__end_++;__swap_out_circular_buffer(__v);
}

上边是分配内从,我们重点看下__swap_out_circular_buffer(__v);  把老的元素拷贝新的申请区域上

template <class _Tp, class _Allocator>
void
vector<_Tp, _Allocator>::__swap_out_circular_buffer(__split_buffer<value_type, allocator_type&>& __v)
{__annotate_delete();__alloc_traits::__construct_backward(this->__alloc(), this->__begin_, this->__end_, __v.__begin_);_VSTD::swap(this->__begin_, __v.__begin_);_VSTD::swap(this->__end_, __v.__end_);_VSTD::swap(this->__end_cap(), __v.__end_cap());__v.__first_ = __v.__begin_;__annotate_new(size());__invalidate_all_iterators();
}

在看下__alloc_traits::__construct_backward 这块 代码

    template <class _Ptr>_LIBCPP_INLINE_VISIBILITYstaticvoid__construct_backward(allocator_type& __a, _Ptr __begin1, _Ptr __end1, _Ptr& __end2){while (__end1 != __begin1){construct(__a, _VSTD::__to_raw_pointer(__end2-1), _VSTD::move_if_noexcept(*--__end1));--__end2;}}

代码看到这里,基本已经水落石出了, 我们看到上边有一个很关键的代码_VSTD::move_if_noexcept(*--__end1), 从字面意思也能看出来它是什么意思, 接着看下它的源码

emplate <class _Tp>
inline _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_AFTER_CXX11typename conditional
<!is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value,const _Tp&,_Tp&&
>::typemove_if_noexcept(_Tp& __x) _NOEXCEPT
{return _VSTD::move(__x);
}

这块代码就比较复杂了, move_if_noexcept 返回值使用了SFINA的技术,  conditional是一个条件判断语句, 如果它第一类型是true, 则返回const_TP&, 如果是false 则返回类型 _Tp&& , 那就看下!is_nothrow_move_constructible<_Tp>::value && is_copy_constructible<_Tp>::value 这个到底表达什么意思, 从标准库源代码is_nothrow_move_constructible<_Tp>::value 是判断_TP这个类型是否有不抛一场的移动构造方法, is_copy_constructible<_Tp>::value 并且拷贝构造方法, 

源码看到这里大家心里就很清楚了, 到底咋回事!

http://www.yayakq.cn/news/628788/

相关文章:

  • 广告留电话号的网站杭州优化外包哪里好
  • 优化问题网站德阳 网站建设
  • 济南网站建设q.479185700惠2024的新闻有哪些
  • 立码软件做网站用别人服务器做网站
  • 公司网站设新闻摘抄
  • 网站前台用什么做wordpress ts cd
  • 在东营怎么建网站百度引擎的搜索方式是什么
  • 十堰学网站建设培训班wordpress 页面与文章
  • 做网站店铺怎样打理做网站编辑需要会什么
  • 老鸭窝网站正在建设中跨境电商网站建设方案
  • 厦门it做网站最强做网站订房网站
  • 花钱想贷款结果成了做网站雄安网站建设制作
  • 关于协会网站建设的建议弄一个网站
  • 网站服务器租用方法网站建设大数据
  • 合肥做公司网站网站模板展示
  • 做微网站需要域名吗网页动态效果
  • 好的网页设计网站长春网站上排名
  • 深圳网站建设外贸新手做网站什么类型
  • 大区直播间网站开发制作福州建设工程质量监督网站
  • 事业单位网站开发工作规程百度地图收录提交入口
  • 留住用户网站优化营商环境工作总结
  • 建设机械网站方案做药的常用网站有哪些
  • 宁波做网站皆选蓉胜网络潍坊高端网站建设
  • php服装网站模板计算机培训机构哪个最好
  • 网站一键收录网站开发数据库速度解决方法
  • 模板网站对排名的影响户外网站模板
  • wordpress 分享网站正规网站建设公司在哪里
  • 上海外贸网站推广建设网站图
  • 徐州做网站哪个好网站流量统计
  • 企业网站自己可以做吗找个做网站的人