1

我有一个帮助类来释放 MYSQL_RES 句柄。

class auto_mysqlres
{
public:
  auto_mysqlres(MYSQL_RES *res) : m_res(res)
  {
  }

  ~auto_mysqlres()
  {
    if (m_res != NULL)
      mysql_free_result(m_res);
  }

  operator MYSQL_RES* ()
  {
    return m_res;
  }

private:
  auto_mysqlres& operator= (const auto_mysqlres &res);
  auto_mysqlres (const auto_mysqlres &res);

private:
  MYSQL_RES *m_res;
};

当我尝试以这种方式使用它时,我 auto_mysqlres result = return_pointer_to_mysql_res();GCC 4.6.3: auto_mysqlres::auto_mysqlres(const auto_mysqlres&) is private. 但是,MSVC 2008 中没有错误。

return_pointer_to_mysql_res返回MYSQL_RES*,当然我已经解决了这条线的问题auto_mysqlres result (return_pointer_to_mysql_res());

但我想知道为什么会出现这个错误。我不明白为什么 GCC 会在那里创建一个临时对象。

4

2 回答 2

4

您正在这里执行复制初始化

auto_mysqlres result = return_pointer_to_mysql_res();

这要求复制构造函数可用,即使省略了副本。从语义上讲,您正在auto_mysqlres从 RHS 上的指针构造一个临时对象,并在 LHS 上从它复制构造。

您可以改用直接初始化

auto_mysqlres result(return_pointer_to_mysql_res());

在此处查看有关复制初始化和直接初始化的更多信息。

正如@Rapptz 在评论中指出的那样,在 C++11 中,您可以决定让您的类移动可复制(并且可能移动可分配),在这种情况下,移动复制构造函数将在复制初始化中被拾取。

于 2013-07-16T12:33:10.617 回答
0

嗯.. @myself:学习永无止境。:)

您的构造函数不是显式的,因此是一种将 a 隐式转换MYSQL_RES*为 as的方法auto_mysqlres。这就是 gcc 在这里所做的。它将 a 转换MYSQL_RES*为 a auto_mysqlres,然后尝试调用复制构造函数。这是必需的。

§ 8.5 [dcl.init] / 14

表单中发生的初始化

  • T x = a;

[...] 称为复制初始化。

你复制初始化你的对象。

§ 8.5 [dcl.init] / 16

[...如果初始化]是复制初始化,其中源类型的 cv 非限定版本与目标类相同或派生类,则考虑构造函数。[...]

否则(即,对于剩余的复制初始化情况),可以从源类型转换到目标类型或(当使用转换函数时)到其派生类的用户定义转换序列被枚举,如 13.3 中所述。 1.4,通过重载决议选择最好的。

在您的情况下MYSQL_RES*,与目标类 ( auto_mysqlres) 的类或派生类不同,因此需要进行转换,因为不考虑构造函数。

你要么

  • 必须直接初始化

    auto_mysqlres result(return_pointer_to_mysql_res());

  • 或提供(移动)复制构造函数。

PS:不是很清楚where the cv-unqualified version of the source type is the same class as, or a derived class of, the class of the destination

于 2013-07-16T12:26:45.077 回答