关于C++ 中 thread 的拷贝构造函数

起因来自于《C++并发编程实战》的这样一个例子

#include <thread>
#include <iostream>
#include <stdexcept>

class ScropeThread
{
public:
    ScropeThread(std::thread t) :m_pThead(std::move(t))
    {
        if (!m_pThead.joinable())
        {
            throw std::logic_error("no thread");
        }
    }
    ~ScropeThread()
    {
        m_pThead.join();
    }
    ScropeThread(const ScropeThread &) = delete;
    ScropeThread& operator=(const ScropeThread &) = delete;

private:
    std::thread m_pThead;
};

void fun(void){}
int main()
{
    ScropeThread(std::thread(fun));

    return 0;
}

我“灵机一动”,将main函数变成了这个亚子:

int main()
{
    std::thread t1(fun);
    ScropeThread st(t1);

    return 0;
}

编译器毫不犹豫的给我报错了:

一个是先定义了一个thread对象t1,然后用将t1作为参数传入scropethread的构造函数,一个是定义了一个临时的thread对象,然后将其传入scropethread的参数列表。

这两种方法都需要利用拷贝构造函数将实参拷贝给形参,即这两种方法都用到了thread类的拷贝构造函数

报错的原因用人话来说就是thread类没有定义拷贝构造函数。我百思不得其解。

折腾了快两个小时。突然福至心灵,想到了c++中右值的概念。对哟,以第一种方式将参数传入scropethread的构造函数时,我在参数列表里建立了一个临时的 std::thread(fun),这是一个右值

而当我在外面这样定义时: std::thread t1(fun);t1是一个左值

而错误的真正原因是:thread类没有定义以左值作为参数的拷贝构造函数,但却有以右值作为参数的拷贝构造函数。

点进thread类的头文件,果然如此:

从头文件中,我们也可以得出一个结论:thread对象是不能复制(copy)的,只能移动(move)

原文地址:https://www.cnblogs.com/XiaoXiaoShuai-/p/11334374.html

时间: 2024-11-08 18:48:47

关于C++ 中 thread 的拷贝构造函数的相关文章

c++中树的拷贝构造函数的迭代实现

具体思想是通过遍历目标树,保存对应的左右孩子节点位置.以按顺序拷贝对应位置的内容. 这里用先序遍历的原因是为了当要取等待拷贝的节点的左右孩子的位置,可以保证此节点存在.避免访问NULL使程序跳出. template<typename T> inline BinTree<T>::BinTree(BinTree & binTree) { BinNodePosi(T) otherTreeNode; stack<BinNodePosi(T)>otherBinNodeSt

关于 C++ 拷贝构造函数(copy constructor)中的形参必须为引用类型的详解

在<C++ primer>中文第四版中,关于拷贝构造函数(也称复制构造函数)是这样定义的:是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用. 问题来了!为什么形参必须为该类类型的引用?而不能是值传递方式?(PS:其实传值和传址都可以统一为传值,前者传的是对象的值,后者传的是对象的地址的值) 先看下边两组代码: 1. 1 class Example { 2 3 public: 4 5 Example() {} 6 7 Example(const Example&a

拷贝构造函数和赋值操作符

假设有一个如下的MyClass类: class MyClass { public: //构造函数 //拷贝构造函数 MyClass(const MyClass& that) : int_data_(that.int_data_), dbl_data_(that.dbl_data_), str_data_(that.str_data_) { } //赋值操作符 MyClass& operator = (const MyClass& that) { if(this != that) {

拷贝构造函数

类进行拷贝初始化时会调用拷贝构造函数,拷贝初始化发生在以下几种情况中: [1] 有"="的地方会发生拷贝; [2] 将一个对象作为参数传递给一个非引用的对象时; [3] 从一个返回类型为引用的类型的函数返回一个对象; [4] 用花括号初始化一个数组中的元素; 拷贝构造函数的形参必须为引用类型,我认为应该有两点原因: 1. 在类的类部定义该类的对象,只能定义为引用类型或指针类型,因为其属于不完全类型: 2. 如果不定义为引用就会陷入无限的循环--调用拷贝构函数,必须拷贝它的实参,而拷贝它

C++拷贝构造函数(浅拷贝、深拷贝)

下面举一个简单的例子说明对象之间的拷贝(此例中没有自定义拷贝构造函数,在调用拷贝构造函数的时候,编译器会自动生成一个默认的拷贝构造函数,该构造函数完成对象之间的位拷贝)浅拷贝: #include<iostream> using namespace std; class CExample { private:int a; public: CExample(int b) { a=b; } void Show() { cout<<a<<endl; } }; int main(

【转】 c++拷贝构造函数(深拷贝,浅拷贝)详解

c++拷贝构造函数(深拷贝,浅拷贝)详解 2013-11-05 20:30:29 分类: C/C++ 原文地址:http://blog.chinaunix.net/uid-28977986-id-3977861.html 一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream

c++拷贝构造函数(深拷贝,浅拷贝)详解

一.什么是拷贝构造函数      首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=100; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量.  下面看一个类对象拷贝的简单例子. #include<iostream> using namespace std; class CExample { private: int a; public: //构造函数 CExample(int b) { a=b; printf("con

C++拷贝构造函数

在C++中,下面三种对象需要调用拷贝构造函数!1. 对象以值传递的方式传入函数参数 [c-sharp] view plaincopy class CExample    {   private:    int a;      public:    //构造函数    CExample(int b)    {      a = b;     cout<<"creat: "<<a<<endl;    }       //拷贝构造    CExample(

拷贝构造函数和赋值函数

在 C++ 中,赋值和拷贝是不同的, 1)拷贝构造函数是对未初始化的内存进行初始化操作 2)而赋值是对现有的已经初始化的对象进行操作.(这里我对"已经初始化"的理解是已经调用了构造函数,并且构造函数体可以未执行,只要调用到即可),赋值函数应该给所有数据成员都初始化. 3)重点:包含动态分配成员的类 应提供拷贝构造函数,并重载"="赋值操作符. 4)可以说,C++中什么时候有临时对象产生,此时刻c++一定要调用拷贝构造函数.(临时对象产生时有一个特例,此时不需要调用拷