【问题标题】:shared_ptr requires complete type; cannot use it with lua_State*shared_ptr 需要完整的类型;不能与 lua_State* 一起使用
【发布时间】:2011-01-26 21:08:30
【问题描述】:

我正在为 Lua 编写 C++/OOP 包装器。我的代码是:

class LuaState
{
     boost::shared_ptr<lua_State> L;

     LuaState(): L( luaL_newstate(), LuaState::CustomDeleter )
     {
     }
}

问题是 lua_State 类型不完整,shared_ptr 构造函数需要完整类型。我需要安全的指针共享。 (有趣的是 boost 文档说大多数函数不需要完整的类型,但构造函数需要,所以没有办法使用它。http://www.boost.org/doc/libs/1_42_0/libs/smart_ptr/smart_ptr.htm

我能解决这个问题吗?谢谢。

【问题讨论】:

  • 如果我可能会问,为什么需要安全指针共享。你不能只在构造函数中调用 luaL_newstate 并在析构函数中调用 lua_close。
  • LuaState a, b; a = b; // b 中的 lua_State 将永远不会被释放 // a 中的 lua_State 将被释放两次 另一种选择是在复制构造函数和 operator= 中克隆 lua_State 结构。但我想这是一个沉重的解决方案。
  • 您不能手动克隆 lua_State 结构。它会在你的脸上炸开。我试过了:)
  • 我就是这么想的。 :) 那么,安全管理 lua_State* 的解决方案是什么?

标签: c++ boost lua shared-ptr


【解决方案1】:

您正在使用自己的删除器,这意味着您不必在构造时拥有完整的类型。唯一的要求是CustomDeleter 可以处理。 (它可能会将传递的指针转换为完整类型,例如(例如,从 void*CompleteType*)。

完整性的背景是,一旦使用默认删除器调用shared_ptr 的构造函数,它将实例化一个包含delete p; 行的类——为了使这段代码正确,p 不能是不完整。析构函数会间接调用这个删除器代码,所以它不依赖于类型的完整性。

但是,如果您通过自己的删除器,则将适用您自己的删除器的要求。确保在完成lua_State 之后定义CustomDeleter

【讨论】:

  • 感谢您的反馈。你的代码正是我写的。它在静态检查“typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];”中的“shared_ptr::checked_delete”中失败
  • @topright,如果您使用自己的删除程序正确,它不应该那样失败。请务必定义您的CustomDeleter,使其主体出现在lua_State 的定义之后。
【解决方案2】:

boost::shared_ptr 需要一个完整的类型来实例化似乎很奇怪,所以我编写了这个小测试来演示相反的情况(代码在最后)。

我认为问题不在于需要完整的类型,而在于您传递给shared_ptr 构造函数的第二个参数,它看起来像一个成员函数。第二个参数必须是可以使用单个指针参数调用的东西。如果您想使用包装器的成员函数,您可以使用boost::bind 来调整接口。

也许你的意思是?:

 LuaState(): L( luaL_newstate(), boost::bind(LuaState::CustomDeleter,this,_1) )
 {
 }

证明boost::shared_ptr 不需要完整的类型:

// forward declarations
struct test;
test * create();
void destroy(test *);

// wrapper equivalent to the one in the question
struct wrapper {
   boost::shared_ptr<test> sp;
   wrapper() : sp( create(), destroy ) {}
};

// actual definitions
struct test {};
test * create() { return new test; }
void destroy(test *t) { delete t; }

// make it executable
int main() {
   test t;
}

【讨论】:

    【解决方案3】:

    鉴于无法克隆 lua_State*,复制 LuaState 对象有意义吗?复制这种固有的不可复制对象的预期语义是什么?

    您似乎想要的行为是 浅复制 - 最好的方法是让 LuaState 不可复制并管理 lua_State 的生命周期,然后您可以将状态作为 @ 987654321@.

    【讨论】:

      猜你喜欢
      • 2013-07-13
      • 2012-02-24
      • 2017-03-29
      • 2019-01-03
      • 2018-09-12
      • 2022-08-13
      • 1970-01-01
      • 1970-01-01
      • 2014-10-13
      相关资源
      最近更新 更多