Ich habe meinen Code wie folgt vereinfacht.Warum C++ - Destruktor das Verhalten der Rückgabewertoptimierung beeinflussen
#include <vector>
class NoncopyableItem {
public:
NoncopyableItem() { }
NoncopyableItem(NoncopyableItem &&nt) { };
};
class Iterator {
friend class Factory;
public:
~Iterator() { } // weird
private:
Iterator() { }
std::vector<NoncopyableItem> buffer_;
};
class Factory {
public:
Iterator NewIterator() {
return Iterator();
}
};
int main() {
Factory fa;
auto it = fa.NewIterator();
return 0;
}
Ich möchte NewIterator
die RVO (Rückgabewert Optimierung) in Funktion nutzen, aber ich habe den folgenden Fehler:
In file included from /usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/vector:62:0,
from /cygdrive/c/Users/DELL/ClionProjects/destructor_test/main.cpp:1:
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_construct.h: In instantiation of 'void std::_Construct(_T1*, _Args&& ...) [with _T1 = NoncopyableItem; _Args = {const NoncopyableItem&}]':
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_uninitialized.h:75:53: required from 'static _ForwardIterator std::__uninitialized_copy<_TrivialValueTypes>::__uninit_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const NoncopyableItem*, std::vector<NoncopyableItem> >; _ForwardIterator = NoncopyableItem*; bool _TrivialValueTypes = false]'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_uninitialized.h:126:41: required from '_ForwardIterator std::uninitialized_copy(_InputIterator, _InputIterator, _ForwardIterator) [with _InputIterator = __gnu_cxx::__normal_iterator<const NoncopyableItem*, std::vector<NoncopyableItem> >; _ForwardIterator = NoncopyableItem*]'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_uninitialized.h:279:63: required from '_ForwardIterator std::__uninitialized_copy_a(_InputIterator, _InputIterator, _ForwardIterator, std::allocator<_Tp>&) [with _InputIterator = __gnu_cxx::__normal_iterator<const NoncopyableItem*, std::vector<NoncopyableItem> >; _ForwardIterator = NoncopyableItem*; _Tp = NoncopyableItem]'
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_vector.h:324:32: required from 'std::vector<_Tp, _Alloc>::vector(const std::vector<_Tp, _Alloc>&) [with _Tp = NoncopyableItem; _Alloc = std::allocator<NoncopyableItem>]'
/cygdrive/c/Users/DELL/ClionProjects/destructor_test/main.cpp:7:7: required from here
/usr/lib/gcc/x86_64-pc-cygwin/4.9.3/include/c++/bits/stl_construct.h:75:7: error: use of deleted function 'constexpr NoncopyableItem::NoncopyableItem(const NoncopyableItem&)'
{ ::new(static_cast<void*>(__p)) _T1(std::forward<_Args>(__args)...); }
^
/cygdrive/c/Users/DELL/ClionProjects/destructor_test/main.cpp:2:7: note: 'constexpr NoncopyableItem::NoncopyableItem(const NoncopyableItem&)' is implicitly declared as deleted because 'NoncopyableItem' declares a move constructor or move assignment operator
class NoncopyableItem {
^
CMakeFiles/destructor_test.dir/build.make:62: recipe for target 'CMakeFiles/destructor_test.dir/main.cpp.o' failed
Nach cppreference.com, NewIterator()
sollte das Erfordernis der RVO erfüllen. Es scheint jedoch, dass der Compiler versucht, den Standardkopiekonstruktor Iterator
aufzurufen, und schlägt dann fehl, weil Iterator.buffer_
nicht kopierbar ist.
Nun zu meiner Überraschung, wenn ich den Destruktor von Iterator
in L # 13 lösche, funktioniert der Code gut.
Warum beeinflusst der Destruktor das RVO-Verhalten des Compilers?
Nicht ganz richtig. 'Iterator (const Iterator &);' wird implizit deklariert und als Standard definiert (nicht gelöscht). Der Kopierkonstruktor von 'std :: vector' kann jedoch nicht instanziiert werden. ('std :: vector ' hat einen barrierefreien Copy-Konstruktor, was die Überprüfung der Kopierbarkeit der Elemente betrifft.) Daher der Fehler des OPs. –
@ T.C. Danke, behoben. Es wird jedoch als gelöscht am 12.7.11 in N4140 definiert, oder? –
Nein, der Kopierkonstruktor von 'Iterator' wird nicht wirklich gelöscht, da der Vektor nominal * * einen barrierefreien und nicht gelöschten Kopierkonstruktor hat. 'static_assert (std :: is_copy_constructible {}," ");' wird * nicht * ausgelöst. Die implizite Definition des Kopierkonstruktors von 'Iterator' löst die Instanziierung des Kopierkonstruktors des Vektors aus, was einen schweren Fehler verursacht. –