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

莱芜市网站建设wordpress 4.7.11搬家

莱芜市网站建设,wordpress 4.7.11搬家,建设外贸网站要多少钱,怎么自己设置网站模板目录 一、问题引出 二、示例代码及输出结果 三、详细解释 关键点解析 1. 第一次拷贝构造:临时对象(mData101) 2. 第二次拷贝构造:线程内部存储对象(mData102) 3. 第三次拷贝构造:线程函数…

目录

一、问题引出

二、示例代码及输出结果

三、详细解释

关键点解析

1. 第一次拷贝构造:临时对象(mData=101)

2. 第二次拷贝构造:线程内部存储对象(mData=102)

3. 第三次拷贝构造:线程函数参数 p4(mData=103)

析构顺序验证

结论


一、问题引出

函数原型详见
https://en.cppreference.com/w/cpp/thread/thread/thread

本文只讲第三个形式。

c++标准规定

根据C++的标准,当使用std::thread创建线程时,所有的参数都会被拷贝到线程的内部存储中,然后再传递给线程函数。这是因为线程可能在参数所在的作用域结束后才执行,所以必须确保参数的生存期足够长。所以,当传递对象作为参数时,会进行一次拷贝构造,创建该对象的副本,存储在线程的内部。

为了验证上述规则。写一段示例代码看看。

二、示例代码及输出结果

代码:

#include<iostream>
#include<thread>
#include<string>class Foo{
public:Foo(int d):mData(d){std::cout<<"Foo():"<<this<<" :"<<mData<<std::endl;}Foo(const Foo& foo){mData = foo.mData + 1;std::cout<<"Foo(const Foo& foo):"<<this<<" :"<<mData<<std::endl;}~Foo(){std::cout<<"~Foo():"<<this<<" :"<<mData<<std::endl;}int getData() const{return mData;}
private:int mData;
};void threadFunc(int p1,float p2,std::string p3,Foo p4)
{std::this_thread::sleep_for(std::chrono::seconds(2));std::cout<<p1<<" ,"<<p2<<" ,"<<p3<<" ,"<<&p4<<":"<<p4.getData()<<std::endl;
}int main(int argc,char* argv[])
{{std::thread t1;{float fd = 1.23;Foo foo1(100);//所有的参数都会被复制t1 = std::thread(threadFunc,12,fd,"test string para",foo1);}t1.join();}std::cout<<"exit"<<std::endl;return 0;
}

输出结果:

Foo():0x7fffd0445520 :100
Foo(const Foo& foo):0x7fffd04454a0 :101
Foo(const Foo& foo):0x55a08cdd72c8 :102
~Foo():0x7fffd04454a0 :101
~Foo():0x7fffd0445520 :100
Foo(const Foo& foo):0x7f5b04383d8c :103
12 ,1.23 ,test string para ,0x7f5b04383d8c:103
~Foo():0x7f5b04383d8c :103
~Foo():0x55a08cdd72c8 :102
exit

先看内层块作用域的float fd变量。当内层块作用域结束之后,foo1和fd将失效,从第7行输出可以看到最终线程t1中仍然打印出了1.23,即正确的原来的fd的值。这就说明在构造t1是fd被拷贝到了t1线程内部。

再看foo1对象。原始foo1对象的析构是在内层块作用域结束时发生的,打印输出了第5行。从输出的第2行可以看到在构造线程t1时,确实是先发生了对foo1的拷贝构造。这印证了c++标准中的规定。

更多疑惑:为什么会发生三次拷贝构造?

第4行和第5行输出,表明在原始的foo1对象被析构之前先析构了第一次拷贝构造的对象(101)。这是为什么呢?如果第一次拷贝构造得到的对象(101)是线程内部存储的对象的话,那这个对象不应该这么早就被析构掉,而是应该跟随线程t1的生命周期在外层块作用域结束时被析构。所以有理由认为第一次拷贝构造得到的对象是一个临时对象,第二次拷贝构造得到的对象(102)才是线程内部存储的对象。第9行输出印证了这一观点。

以下是对这一段代码的详细解释。

三、详细解释

关键点解析

通过代码和输出,可以明确三次拷贝构造的来源及析构顺序:


1. 第一次拷贝构造:临时对象(mData=101

  • 触发时机:当调用 std::thread 构造函数时,参数 foo1 需要被传递到线程的内部存储。

  • 具体过程

    • 参数 foo1 是左值,需通过 decay-copy 生成一个临时副本。

    • 此处触发第一次拷贝构造函数:

      Foo(const Foo& foo):0x7fffd04454a0 :101
  • 析构时机

    • 这个临时对象在 std::thread 构造函数完成后立即析构(因为它仅用于初始化线程的内部存储)。

    • 对应输出中的析构顺序:

      ~Foo():0x7fffd04454a0 :101  // 临时对象析构
      ~Foo():0x7fffd0445520 :100  // 原始对象析构

2. 第二次拷贝构造:线程内部存储对象(mData=102

  • 触发时机:线程启动时,需要将参数从主线程传递到新线程的上下文。

  • 具体过程

    • 临时对象(mData=101)会被移动(或拷贝,若无移动语义)到线程的内部存储。

    • 由于 Foo 未定义移动构造函数,此处触发第二次拷贝构造函数:

      Foo(const Foo& foo):0x55a08cdd72c8 :102
  • 生命周期

    • 该对象存储在线程内部,直到线程执行完毕才会析构。

    • 对应输出中的析构顺序:

      ~Foo():0x55a08cdd72c8 :102  // 线程内部对象析构(在 `t1.join()` 之后)

3. 第三次拷贝构造:线程函数参数 p4mData=103

  • 触发时机:线程函数 threadFunc 的参数 p4 是按值传递的。

  • 具体过程

    • 线程内部存储的对象(mData=102)需要拷贝到 p4 中。

    • 触发第三次拷贝构造函数:

      Foo(const Foo& foo):0x7f5b04383d8c :103
  • 生命周期

    • p4 在 threadFunc 执行结束时析构。

    • 对应输出中的析构顺序:

      ~Foo():0x7f5b04383d8c :103  // 函数参数析构

析构顺序验证

  • 原始对象 foo1mData=100

    • 在其所在块作用域结束时析构({ ... Foo foo1(100); ... } 结束)。

  • 临时对象(mData=101

    • 在 std::thread 构造函数完成后立即析构。

  • 线程内部存储对象(mData=102

    • 在 t1.join() 后析构(线程完全结束时)。

  • 函数参数 p4mData=103

    • 在 threadFunc 执行结束时析构。

输出结果与上述逻辑完全一致:

~Foo():0x7fffd04454a0 :101  // 临时对象析构
~Foo():0x7fffd0445520 :100  // 原始对象析构
~Foo():0x7f5b04383d8c :103  // 函数参数析构
~Foo():0x55a08cdd72c8 :102  // 线程内部存储对象析构

结论

  1. 第一次拷贝构造是为了生成临时对象,用于初始化线程内部存储。

  2. 第二次拷贝构造是将临时对象移动到线程的内部存储(由于缺乏移动语义,退化为拷贝)。

  3. 第三次拷贝构造是将线程内部存储的对象传递给函数参数 p4(按值传递)。

析构顺序由对象的生命周期决定:

  • 临时对象和原始对象在主线程析构。

  • 线程内部存储对象在线程结束后析构。

  • 函数参数在函数结束时析构。


文章转载自:

http://vsVFUnVL.Lgtcg.cn
http://RDsVbjiJ.Lgtcg.cn
http://b2gK4ppS.Lgtcg.cn
http://BSbfoMlL.Lgtcg.cn
http://x5KEoDVl.Lgtcg.cn
http://ZoRjv4JO.Lgtcg.cn
http://ctWvITj8.Lgtcg.cn
http://slHHuvq3.Lgtcg.cn
http://2RLoBqcG.Lgtcg.cn
http://gO92AYQr.Lgtcg.cn
http://r2WmvJuB.Lgtcg.cn
http://mewynOPd.Lgtcg.cn
http://YTO4iriX.Lgtcg.cn
http://VKkBcGpd.Lgtcg.cn
http://aNByfNR4.Lgtcg.cn
http://6UOfqkWS.Lgtcg.cn
http://m2iHytvH.Lgtcg.cn
http://ubUM6zL0.Lgtcg.cn
http://jBCmsAWM.Lgtcg.cn
http://w46o8oXw.Lgtcg.cn
http://0ceu7Wot.Lgtcg.cn
http://Mg7BoLo4.Lgtcg.cn
http://4UKBywqZ.Lgtcg.cn
http://Vr2BDKno.Lgtcg.cn
http://dG53AUtZ.Lgtcg.cn
http://qapCYmdu.Lgtcg.cn
http://MvW4mqeA.Lgtcg.cn
http://p9AA87Y1.Lgtcg.cn
http://iIP1c9eA.Lgtcg.cn
http://dNkr89oO.Lgtcg.cn
http://www.dtcms.com/wzjs/634639.html

相关文章:

  • 太湖县住房和城乡建设局网站搜索引擎优化步骤
  • 网站建设标准规范wordpress安装资料夹
  • 唐山哪里有建设网站的网站建设综合实训
  • 如何给WordPress网站更换域名给你一个网站怎么做的
  • 做网站在哪里做做那个类型的网站赚钱
  • 郴州市建设网站网站站外优化推广方式
  • 网站开发方式演进wordpress php 链接地址
  • 软件库网站源码哪个公司需要做网站
  • 网站外包价格 北京网站制作公司知名网站建设多少钱
  • 网站的设计风格与特点关键词挖掘站长工具
  • 保护环境网站模板合肥房产信息网
  • 阿里巴巴官网网站网站的跳出率很高
  • 网站开发英语上海建设工程交易中心
  • 鄂州网站制作企业网站空间 流量
  • 二手车东莞网站建设拼多多代运营
  • 网站制作架构成都网站建设推来客
  • 商城网站开发制作自己如何做公司网站视频
  • 杭州哪家公司做网站比较好用什么软件做网站最好
  • 网站建设论文标题网站的内链建设
  • 腾讯网站备案三端互通传奇手游找服网站
  • 海门市住房和城乡建设局网站专题网站建设自查整改报告
  • 响应式网站 推广效果wordpress伪静态说明
  • 广州上市网站建设的公司想做个人域名网站怎么做
  • 建商城网站网站建设的素材
  • 网站建设和源代码问题企业网站建设组织人员可行性分析
  • 飞鱼网站建设浙江职业能力建设网站
  • 企业网站备案号密码忘记我市精神文明建设的门户网站
  • 企业网站的制作周期外贸信息发布平台
  • 网站如何不被百度搜到wordpress发外链
  • 网站色差表广州互联网广告推广