c++ - 使用 phoenix 构造时调用析构函数

标签 c++ boost boost-spirit-qi boost-phoenix

我正在开发一个 Boost Spirit Qi 项目,该项目使用 phoenix::construct 创建一个对象,该对象具有指向另一个对象的指针。我注意到使用 phoenix::construct 会在某个时候调用析构函数(我猜是在函数的末尾)。为什么调用析构函数?我该如何解决这个问题?

注意:这不是我的实际代码,我做了一个玩具示例,所以不会太长

对象

class Bar
{
public:
    Bar(int y)
    {
        this->x = y;
    }

    ~Bar()
    {
    }

    int x;
};

class Foo
{
public:

    Foo()
    {
    }

    Foo(Bar* bar) : _bar(bar)
    {
    }

    ~Foo()
    {
        delete this->_bar;
    }

    void DoStuff()
    {
        std::cout << this->_bar->x << std::endl;
    }

private:
    Bar *_bar;
};

语法

template <typename Iterator>
struct TestGrammar : qi::grammar < Iterator, Foo(), ascii::space_type >
{
    TestGrammar() : TestGrammar::base_type(foo)
    {
        foo = bar[qi::_val = phoenix::construct<Foo>(qi::_1)];
        bar = qi::double_[qi::_val = phoenix::new_<Bar>(qi::_1)];
    }

    qi::rule < Iterator, Foo(), ascii::space_type > foo;
    qi::rule < Iterator, Bar*(), ascii::space_type> bar;
};

调用代码

std::getline(std::cin, string);

iter = string.begin();
end = string.end();

bool result = qi::phrase_parse(iter, end, grammar, space, f);

if (result)
{
    State s;
    f.DoStuff();
}
else
{
    std::cout << "No Match!" << std::endl;
}

最佳答案

析构函数运行在foo规则的属性上;那是在它被复制到引用的属性之后。

由于您的 Foo 类违反了三规则,这会导致问题。 Foo 不应是可复制的(或实现深层复制)。

这样标记:

class Foo : public boost::noncopyable {

将显示语法复制了 Foo:

/home/sehe/custom/boost_1_57_0/boost/proto/transform/default.hpp|154 col 9| error: use of deleted function ‘Foo& Foo::operator=(const Foo&)’

简而言之:

  1. 使用零规则或{三|五规则编写卫生类}
  2. 不要在 Spirit 语法中进行动态分配。它会让你悲伤。
  3. 不要执行语义操作 ( Boost Spirit: "Semantic actions are evil"? )

这是通过实现三规则的快速修复版本:

Live On Coliru

struct Foo {
    Foo(Bar *bar = 0) : _bar(bar) {}
    Foo(Foo const& o) : _bar(new Bar(*o._bar)) {}
    Foo& operator=(Foo const& o) { 
        Foo tmp;
        tmp._bar = new Bar(*o._bar);
        std::swap(tmp._bar, _bar);
        return *this;
    }

    ~Foo() { delete _bar; }

    void DoStuff() { std::cout << _bar->x << std::endl; }

  private:
    Bar *_bar;
};

这里有一个使用零规则的稍微不那么快速和肮脏的方法:

Live On Coliru

struct Foo {
    using PBar = boost::shared_ptr<Bar>;
    Foo(PBar bar = {}) : _bar(bar) {}

    void DoStuff() { std::cout << _bar->x << std::endl; }

private:
    PBar _bar;
};

完整代码

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
#include <boost/make_shared.hpp>

namespace qi      = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace ascii   = boost::spirit::ascii;

struct Bar {
    Bar(int y) { this->x = y; }
    ~Bar() {}

    int x;
};

struct Foo {
    using PBar = boost::shared_ptr<Bar>;
    Foo(PBar bar = {}) : _bar(bar) {}

    void DoStuff() { std::cout << _bar->x << std::endl; }

  private:
    PBar _bar;
};

template <typename Iterator>
struct TestGrammar : qi::grammar<Iterator, Foo(), ascii::space_type>
{
    TestGrammar() : TestGrammar::base_type(foo)
    {
        using namespace qi;
        foo = bar     [ _val = phoenix::construct<Foo::PBar>(_1) ] ;
        bar = double_ [ _val = phoenix::new_<Bar>(_1)      ] ;
    }

    qi::rule<Iterator, Foo(), ascii::space_type> foo;
    qi::rule<Iterator, Bar*(), ascii::space_type> bar;
};

int main() {
    std::string input;
    std::getline(std::cin, input);

    using It = std::string::const_iterator;
    It iter = input.begin();
    It end = input.end();

    TestGrammar<It> grammar;
    Foo f;
    bool result = qi::phrase_parse(iter, end, grammar, ascii::space, f);

    if (result) {
        //State s;
        f.DoStuff();
    } else {
        std::cout << "No Match!" << std::endl;
    }
}

关于c++ - 使用 phoenix 构造时调用析构函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29798376/

相关文章:

c++ - boost::asio 从套接字读取 n 个字节到 streambuf

c++ - 使用 Spirit::Qi 进行语法解析失败

c++ - 语法平衡问题

c++ - 如何通过 boost spirit 提取 std::string 对象

c++ - 循环正确填充数组然后函数返回所有相同数字的数组?

c++ - 使用进程间映射 boost 模板错误

c++ - 是否可以在私有(private)内存空间中分配一个用于 boost 托管共享内存的对象?

c++ - 通过本地代理将 GET 发送到 google。 C++。 Linux。传输控制协议(protocol)

c++ - 在 pkg-config 搜索路径中找不到包 webkitgtk-3.0

c++ - 继承构造函数仅部分起作用