C++ 如何摧毁和重建卢厄州

C++ 如何摧毁和重建卢厄州,c++,lua,C++,Lua,对于一个学校项目,我正在使用Lua向游戏引擎添加一些脚本功能。引擎的加载速度非常慢,因此我希望能够重新加载脚本,而不是每次更改Lua脚本时都重新启动引擎。我希望能够以一种安全可靠的方式做到这一点,即使其他脚本作者以不可预测的方式污染了全球状态 在我看来,最简单的方法是在我的C++代码中简单地销毁 LuaSuthOnt/Cuff>,然后创建一个新的代码,重新绑定我的函数并重新加载所有必需的脚本。然而,我在让它正常工作时遇到了一些困难。我有一个类作为Lua虚拟机的接口,它具有以下构造函数和析构函数:

对于一个学校项目,我正在使用Lua向游戏引擎添加一些脚本功能。引擎的加载速度非常慢,因此我希望能够重新加载脚本,而不是每次更改Lua脚本时都重新启动引擎。我希望能够以一种安全可靠的方式做到这一点,即使其他脚本作者以不可预测的方式污染了全球状态

在我看来,最简单的方法是在我的C++代码中简单地销毁<代码> LuaSuthOnt/Cuff>,然后创建一个新的代码,重新绑定我的函数并重新加载所有必需的脚本。然而,我在让它正常工作时遇到了一些困难。我有一个类作为Lua虚拟机的接口,它具有以下构造函数和析构函数:

LuaInterface::LuaInterface()
{
  luaVM = lua_open();
  luaL_openlibs(luaVM);

  // Create the ortsgfx table.
  lua_newtable(luaVM);
  lua_setglobal(luaVM, TABLE_NAME);
}

LuaInterface::~LuaInterface()
{
  // Close the Lua virtual machine
  lua_close(luaVM);
}
请注意,当对象的析构函数执行时,会调用lua_close(luaVM)。我尝试使用以下代码从游戏引擎重置Lua:

lua.~LuaInterface();
lua = LuaInterface();
initLua();
(Lua当然是一个LuaInterface对象。)当我尝试初始化一个表时,这会导致
initLua()
中出现分段错误但是,如果我删除析构函数中的
lua\u close(luaVM)
调用,则一切正常。


我做错了什么?另外,有没有更好的方法来重新加载我的Lua脚本?

我没有看到
initLua
的源代码,所以我只能猜测,但是

你通常不应该随意地玩构造函数和析构函数。照办

lua = LuaInterface();
initLua();

类应该有一个赋值运算符来处理它拥有的<代码> LuaSuthObj/<代码> .p/>

我有C++的经验,但不是Lua,所以我猜:

您的
LuaInterface
类可能不会实现赋值运算符和复制构造函数,否则您可能会将它们与默认构造函数和析构函数一起发布。见三条规则:

如果是这样,那么这一行就是导致错误的原因:

lua = LuaInterface();
因为右侧的
LuaInterface()
将构造一个临时实例,自动生成的
操作符=
lua\u状态
复制到
lua
中。在这一行之后,右侧的未命名临时文件被销毁,并释放出
lua
也认为拥有的
lua\u状态

我想到了三个解决方案:

  • 通过声明私有复制构造函数和赋值运算符,使
    LuaInterface
    不可复制,并且永远不要实现它们。(这是比较常见的:)然后添加一个
    LuaInterface.reset()
    成员函数,该函数的作用与析构函数相同,后跟构造函数。通过将共享部分移动到私有的
    init()
    函数,可以保持代码干净。(注意在这个函数中使用C++异常,将对象置于无效状态)
  • 使
    LuaInterface
    不可复制,但不要使用
    LuaInterface lua
    变量,而是使用指针或
    boost::可选lua
    。这样,您就可以销毁并重新创建变量,而无需手动调用析构函数
  • 通过使用新的
    std::shared\u ptr
    使
    LuaInterface
    成为共享引用类。只需使用
    std::shared_ptr luaVM
    成员变量而不是原始指针,然后在构造函数中调用:

    luaVM.reset(lua_打开(),lua_关闭)

    在这种情况下,您甚至不需要析构函数,但您应该阅读
    shared\u ptr
    以及自动生成的成员现在所做的事情

使用这三种解决方案中的任何一种,您都可以使用简单赋值来重新创建状态:

lua = LuaInterface();
现在我希望问题真的在C++方面,而不是Lua方面

这是未定义的行为。您只需执行
lua=LuaInterface()。如果不遵守三的规则,您还有其他问题,但这也是UB。

(来自未来的问候!我是从另一个Lua问题来到这里的,但我震惊地发现这个问题解决得如此糟糕。希望我能帮助未来的访问者解决这个问题。)

如果要进行就地销毁,则需要进行就地施工。你的方法是错误的

 lua.~LuaInterface();
 new (&lua) LuaInterface();
从这里开始,我建议您熟悉C++11移动语义。然后,可以使用漂亮的语法使类工作

lua = LuaInterface();
// Destructs old instance. Constructs new one. Moves into your variable.
虽然我不建议使用placement析构函数和placement new,但您可以通过这种方式实现赋值运算符

LuaInterface& LuaInterface::operator=(LuaInterface&& other)
{
    if (this != &other)
    {
        this->~LuaInterface();
        new (this) LuaInterface(other);
    }

    return *this;
}

lua_close()是否执行任何内存取消分配?直接调用析构函数后,唯一明智的做法是使用placement new重新初始化变量或释放变量占用的内存,但即使这样也没有意义,因为直接调用析构函数只有在用新的位置初始化变量之后才有意义。。。
LuaInterface& LuaInterface::operator=(LuaInterface&& other)
{
    if (this != &other)
    {
        this->~LuaInterface();
        new (this) LuaInterface(other);
    }

    return *this;
}