繁体   English   中英

使用std :: thread时c ++ 11意外的多态行为

[英]c++11 unexpected polymorphism beahviour when using std::thread

基于带有可变参数函数参数的C ++多态性,我尝试编写类似的(非模板,带构造函数)程序

码:

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    Base (int count) { run(count); } // this-> does not help

    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    using Base::Base;
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

预期结果:

dddd

实际结果(Ubuntu 14.04,gcc v4.8.2):

pure virtual method called
pure virtual method called
terminate called without an active exception
terminate called without an active exception
dAborted (core dumped)

请注意,至少曾经一次真正调用过Derived::operator() (最后一行的d ,几乎总是这样)。

即使代码非常简单,并且几乎与原始代码相同(请参见上面的链接),它也无法工作。 我花了数小时来解决这个问题。

目标是构造具有多个线程的Derived 此数量的线程将在构造函数中执行并在析构函数中加入。 应该将operator()用作线程主体函数(如原始代码中一样)。 而且,它应该是虚拟的以便提供多态性。

就我而言, run通过*this (由于某种原因)键入为Base ,而不是Derived ,因此线程执行纯虚拟的Base::operator()

附加问题:贴标签operator()有什么保护的方法吗?

有人可以帮我吗? 谢谢。

编辑:

根据Billy ONeal的回答,我重新编写了代码,因此Derived构造函数调用run ,但是没有成功

#include <thread>
#include <iostream>
#include <vector>

class Base
{
public:
    virtual void run (int count) { // non-virtual does not help eighter
        for (int i=0; i<count; ++i)
            threads.emplace_back(std::ref(*this));
    }

    virtual ~Base () {
        for (auto& t : threads)
            t.join();
    }

    virtual void operator() () = 0;

protected:
    std::vector< std::thread > threads;
};


class Derived : public Base
{
public:
    Derived (int count) { run(count); }
    virtual void operator() () { std::cout << "d"; }
};


int main()
{
    Derived d(4);
    std::cout << std::endl;
    return 0;
}

结果随时间而变化-这就是我所拥有的

1) d
2) dd
3) ddd
4) dddd
5) d
    pure virtual method called
    terminate called without an active exception
    ddAborted (core dumped)

特别是5)我无法解释。

我在Derived d(4);周围添加了{...} Derived d(4); 作为强制在行结束程序终止之前执行析构函数的匿名块,但是从那以后,我只有

pure virtual method called
terminate called without an active exception
ddAborted (core dumped)

您的代码具有竞争条件(因此存在未定义的行为)。 Base的构造函数中启动线程时,线程将立即尝试在该对象上调用operator() 但是Derived的构造函数尚未运行,因此operator()仍然是Base的构造函数,后者是纯虚拟的。 另一个有效的执行方式是Base的构造函数和Derived的构造函数在线程实际运行之前完成,这将提供您所期望的行为,但是结果不太可能。

您对this->run评论this->run因为输出抱怨调用了纯虚拟成员函数,而run不是纯虚拟成员,只有operator()是。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM