Зачем мне нужен конструктор копирования здесь

У меня есть вспомогательный класс для освобождения дескрипторов 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 создает временный объект там.

1

Решение

Вы выполняете инициализация копии Вот:

auto_mysqlres result = return_pointer_to_mysql_res();

Это требует доступности конструктора копирования, даже если копии удаляются. Семантически, вы строите временный auto_mysqlres от указателя на RHS, и скопируйте конструкцию из него на LHS.

Ты можешь использовать прямая инициализация вместо:

auto_mysqlres result(return_pointer_to_mysql_res());

увидеть больше на скопируйте инициализацию и прямую инициализацию здесь.

Как указывает @Rapptz в комментарии, в C ++ 11 вы можете решить сделать ваш класс перемещаемым копируемым (и, возможно, перемещаемым назначаемым), и в этом случае конструктор перемещения копии будет выбран при инициализации копии.

4

Другие решения

Хорошо .. @myself: Обучение никогда не останавливается. 🙂

Ваш конструктор не является явным и, следовательно, способ неявного преобразования MYSQL_RES* в качестве auto_mysqlres, Это то, что gcc делает здесь. Преобразует MYSQL_RES* в auto_mysqlres а затем пытается вызвать конструктор копирования. Это необходимо здесь.

§ 8.5 [dcl.init] / 14

Инициализация, которая происходит в форме

  • Т х = а;
[…] называется copy-initialization.

Вы копируете-инициализируете свой объект.

§ 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,

0

По вопросам рекламы [email protected]