В одной из своих прошлых статей я рассказывал, что при возврате объектов GCC не использует конструктор копирования, сразу размещая объекты там, где они должны располагаться. Однако, в некоторых случаях GCC требует наличия открытого конструктора копирования.
Рассмотрим программу:
#include <stdio.h> class MyClass { public: int getA() const { return a_; }; explicit MyClass(int a) : a_(a) {}; #if ((__cplusplus) >= 201103L) MyClass& operator = (MyClass &&value) { a_ = value.a_; value.a_ = 0; return *this; }; MyClass(MyClass &&value) : a_(value.a_) { value.a_ = 0; }; #endif private: int a_; MyClass& operator = (const MyClass&) { return *this; }; MyClass(const MyClass&) {}; }; MyClass makeMyClass(int a) { return MyClass(a); } int main() { MyClass mc = makeMyClass(15); printf("a = %d\r\n", mc.getA()); return 0; }
В ней создается класс MyClass, который является перемещаемым, но не копируемым. Его конструктор копирования и оператор присваивания копированием объявлены закрытыми.
Функция makeMyClass возвращает экземпляр класcа MyClass. По сути она реализует что-то похожее на паттерн «фабрика классов».
Теперь главный вопрос: будет ли этот код работать?
Если передать GCC ключ -std=c++11, то данный пример нормально компилируется и работает. Но если ему передать ключ -std=c++98, то увидим ворох ошибок:
main.cpp: In function ‘MyClass makeMyClass(int)’: main.cpp:35:3: error: ‘MyClass::MyClass(const MyClass&)’ is private MyClass(const MyClass&) {}; ^ main.cpp:40:19: error: within this context return MyClass(a); ^ main.cpp: In function ‘int main()’: main.cpp:35:3: error: ‘MyClass::MyClass(const MyClass&)’ is private MyClass(const MyClass&) {}; ^ main.cpp:45:30: error: within this context MyClass mc = makeMyClass(15); ^
GCC ругается на закрытый конструктор копирования. Если объявить его открытым, то ошибка исчезнет. Однако это нарушит саму идею некопируемого класса.
Объявление функции makeMyClass дружественной лишь уменьшает количество ошибок, но не решает саму проблему.
Таким образом, в С++98 нельзя возвращать некопируемые объекты. По крайней мере для компилятора GCC.