我有一个帮助类来释放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会在那里创建一个临时对象。
答案 0 :(得分:4)
您正在此处执行复制初始化:
auto_mysqlres result = return_pointer_to_mysql_res();
这要求复制构造函数可用,即使复制被删除。从语义上讲,您正在从RHS上的指针构造一个临时auto_mysqlres
,并在LHS上复制它。
您可以改为使用直接初始化:
auto_mysqlres result(return_pointer_to_mysql_res());
在copy initialization and direct initializazion here上查看更多内容。
正如@Rapptz在评论中指出的那样,在C ++ 11中,您可以决定让您的类移动可复制(并且可能移动可分配),在这种情况下,移动复制构造函数将在复制初始化中被拾取。
答案 1 :(得分:0)
嗯.. @myself:学习永远不会停止。 :)
您的构造函数不明确,因此可以隐式地将MYSQL_RES*
转换为auto_mysqlres
。这就是gcc在这里所做的。它将MYSQL_RES*
转换为auto_mysqlres
,然后尝试调用复制构造函数。这是必需的。
以
形式出现的初始化
- T x = a;
[...]称为复制初始化。
您复制 - 初始化您的对象。
[...如果初始化]是复制初始化,其中源类型的cv-nonqualified版本与目标类的类相同,或者是派生类,则考虑构造函数。 [...]
否则(即用于剩余的复制初始化情况),用户定义的转换序列可以从源类型转换为目标类型或(当使用转换函数时)转换为其派生类按照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
。