繁体   English   中英

使用std :: future / std :: async

[英]Using std::future/std::async

当我尝试运行下一个代码时,出现一些错误:

// tree.cpp
// compile with: g++ -std=c++11 tree.cpp -o tree

#include <iostream>
#include <future>

using namespace std;

int valtab[127]; // used for integer values of variables

class Tree; // forward declare

class Node {
protected:
    Node() { use = 1; }
    virtual void print(ostream &os) = 0;
    virtual ~Node() { }
    virtual int eval() = 0;
private:
   friend class Tree;
   friend ostream& operator<<(ostream&, const Tree&);
   int use; // reference count
};

class Tree {
public:
    Tree(int n); // constant
    Tree(char id); // variable
    Tree(char op, Tree t); // unary operator
    Tree(char op, Tree left, Tree right); // binary operator
    Tree(const Tree &t) { p = t.p; ++p->use; }
    ~Tree() { if (--p->use == 0) delete p; }
    void operator=(const Tree &t);
    int eval() { return p->eval(); }
private:
    friend class Node;
    friend ostream& operator<<(ostream &os, const Tree &t);
    Node *p; // polymorphic hierarchy
};

void Tree::operator=(const Tree &t)
{
    ++t.p->use;
    if (--p->use == 0) 
        delete p;
    p = t.p;
}

ostream& operator<<(ostream &os, const Tree &t)
{
    t.p->print(os);
    return os;
}

class LeafNode: public Node {
private:
    friend class Tree;
    void print(ostream &os) = 0;
    virtual int eval() = 0;
};

class IntNode: public LeafNode {
public:
    int eval() { return n; }
private:
    friend class Tree;
    int n;
    void print(ostream &os) { os << n ;}
    IntNode(int k): n(k) { }
};

class IdNode: public LeafNode {
public:
    int eval() { return valtab[name]; }
private:
    friend class Tree;
    char name;
    void print(ostream& o) { o << name; }
    IdNode(char id): name(id) { }
};

class UnaryNode: public Node {
public:
    int eval();
private:
    friend class Tree;
    const char op;
    Tree opnd;
    UnaryNode(char a, Tree b): op(a), opnd(b) { }
    void print(ostream& o) { o << "(" << op << opnd << ")"; }
};

int UnaryNode::eval()
{
    switch (op) {
        case '-': return (-opnd.eval());
        case '+': return (+opnd.eval());
        default: cerr << "no operand" << endl;
            return 0;
    }
}

class BinaryNode: public Node {
public:
    int eval();
private:
    friend class Tree;
    const char op;
    Tree left;
    Tree right;
    BinaryNode(char a, Tree b, Tree c): op(a), left(b), right(c) { }
    void print(ostream &os) { os << "(" << left << op << right << ")"; }
};

int BinaryNode::eval()
{
    switch (op) {
        case '-': {
            future<int> left = async(launch::async, left.eval());
            future<int> right = async(launch::async, right.eval());
            //return (left.get() - right.get());
            }
        case '+': return (left.eval() + right.eval());
        case '*': return (left.eval() * right.eval());
        default: cerr << "no operand" << endl;
            return 0;
    }
}

Tree::Tree(int n) { p = new IntNode(n); }
Tree::Tree(char id) { p = new IdNode(id); }
Tree::Tree(char op, Tree t) { p = new UnaryNode(op, t); }
Tree::Tree(char op, Tree left, Tree right) { p = new BinaryNode(op, left, right); }

int main()
{   
    valtab['A'] = 3; valtab['B'] = 4;
    cout << "A = 3, B = 4" << endl;
    Tree t1 = Tree('*', Tree('-', 5), Tree('+', 'A', 4));
    Tree t2 = Tree('+', Tree('-', 'A', 1), Tree('+', t1, 'B'));
    cout << "t1 = " << t1 << ", t2 = " << t2 << endl;
    cout << "t1 = " << t1.eval() << ", t2 = " << t2.eval() << endl;

    return 0;
}

我收到此错误:

error: 'class std::future<int>' has no member named 'eval'

我想更改程序,以便以并行方式对表达式求值。 但是我对未来的实现感到困惑,我不太了解它是如何工作的。 好吧,我知道它是如何工作的,但是我不明白为什么会收到这些错误。

我希望有人能给我一些提示或为我指明正确的方向。

您试图将虚拟成员函数作为异步调用,但未正确提供对象以使其固定。 此外,您同样-ID本地变量的使用,而不是直接引入一个错误,让这个令人难以置信的难以阅读。

我相信这是您要拍摄的内容:

auto eLeft = std::async(std::launch::async, std::bind(&Tree::eval, &this->left));
auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (eLeft.get() - eRight.get());

不过,老实说,这似乎有些过分。 我看不出有什么意义纺纱两个异步操作只需再等上两个 为什么不启动一个 ,然后使用当前线程执行任务的另一半:

auto eRight = std::async(std::launch::async, std::bind(&Tree::eval, &this->right));
return (left.eval() - eRight.get());

std::async的参数是一个函数(或更准确地说,是Callable )。

特别是,您不必自己调用该函数(这会产生返回值)。 调用由std::async

所以这些行:

future<int> left = async(launch::async, left.eval());
future<int> right = async(launch::async, right.eval());

相反,应阅读如下内容:

 future<int> left_result = std::async(launch::async, [this]() { return left.eval(); });
 future<int> right_result = std::async(launch::async, [this]() { return right.eval(); });

请注意,函数调用现在包装在lambda中。 还要注意的是,你还重用了名leftright在你的原代码,这是比较麻烦的。 我在这里将其重命名以使其正常运行。

像往常一样,由于您的程序现在具有并发性,因此您需要关心数据竞争。 当前,这似乎很好,因为树中的所有节点都是不同的,因此异步调用不会彼此共享任何数据。 但是请牢记任何将来的变化。

暂无
暂无

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

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