2015-04-10 8 views
8

unique_ptr silinmiş kopya kurucu için VS2013 derleme Basit bir örnekNasıl Visual Studio

class __declspec(dllexport) A 
{ 
public: 
    vector<unique_ptr<int>> v; 
}; 

Hata ile dll ihraç sınıfta benzersiz işaretçiler vektör kullanmak. __declspec(dllexport) kaldırırsam, sorun değil. Sadece unique_ptr<int> v kullanırsam, bu da iyi. Bu bir derleyici hatası mı? Etrafında çalışmak için herhangi bir yolu? Teşekkürler.

Sen derleyici hatası veren aşağıdaki komple kod

#include <iostream> 
#include <vector> 
#include <memory> 
using namespace std; 

class __declspec(dllexport) A 
{ 
public: 
    vector<unique_ptr<int>> v; 
}; 

int main() 
{ 
    cout << "Hello World" << endl; 
} 

ile http://webcompiler.cloudapp.net/ üzerinde deneyebilirsiniz: örtük ilan kopya kurucusu tanımlamak için O __declspec(dllexport) ekleyerek görünür

Compiled with /EHsc /nologo /W4 /c 
main.cpp 
main.cpp(9): warning C4251: 'A::v': class 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' needs to have dll-interface to be used by clients of class 'A' 
     with 
     [ 
      _Ty=int 
     ] 
c:\tools_root\cl\inc\xutility(2144): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>> &std::unique_ptr<_Ty,std::default_delete<_Ty>>::operator =(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function 
     with 
     [ 
      _Ty=int 
     ] 
c:\tools_root\cl\inc\memory(1430): note: see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::operator =' 
     with 
     [ 
      _Ty=int 
     ] 
c:\tools_root\cl\inc\xutility(2165): note: see reference to function template instantiation '_OutIt std::_Copy_impl<_InIt,_OutIt>(_InIt,_InIt,_OutIt,std::_Nonscalar_ptr_iterator_tag)' being compiled 
     with 
     [ 
      _OutIt=std::unique_ptr<int,std::default_delete<int>> *, 
      _InIt=std::unique_ptr<int,std::default_delete<int>> * 
     ] 
c:\tools_root\cl\inc\vector(973): note: see reference to function template instantiation '_OutIt std::_Copy_impl<std::unique_ptr<int,std::default_delete<_Ty>>,std::unique_ptr<_Ty,std::default_delete<_Ty>>*>(_InIt,_InIt,_OutIt)' being compiled 
     with 
     [ 
      _OutIt=std::unique_ptr<int,std::default_delete<int>> *, 
      _Ty=int, 
      _InIt=std::unique_ptr<int,std::default_delete<int>> * 
     ] 
c:\tools_root\cl\inc\vector(956): note: while compiling class template member function 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &std::vector<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::operator =(const std::vector<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &)' 
     with 
     [ 
      _Ty=int 
     ] 
main.cpp(10): note: see reference to function template instantiation 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &std::vector<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>::operator =(const std::vector<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>> &)' being compiled 
     with 
     [ 
      _Ty=int 
     ] 
main.cpp(9): note: see reference to class template instantiation 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled 
     with 
     [ 
      _Ty=int 
     ] 
+1

Sorun tanımlama, derleyici çıktısı, MCVE - yalnızca tüm SO soruları böyle görünüyorsa! – Angew

+3

Önerebilirsem: Bunu yapmayın. Bu sınıfı sadece bir bağlantı yerine bir DLL'ye koymanın avantajı olarak ne düşünüyorsunuz? DLL'leri (özellikle, yeniden kullanılabilirlik) ana avantajları artık sınıfları dışa aktarırken geçerli değildir. –

+1

Ben ile aynı fikirdeyim. DLL'lerin avantajlarına sahip olmak istiyorsanız, yalnızca bir C API'sini (veya CppCon 2014'te sunulan klasik "kum saati arayüzüne" (https://www.youtube.com/watch?v=PVYdHDm0q6Y) bakın.)). Aksi takdirde, sadece statik bağlantı (.lib/.a dosyaları) kullanın. DLL'leri dağıtırken/yeniden kullanırken C++ ABI sorunları ile uğraşmak, avantajlarının karşılaştırmalı olarak soluklaştığı bir kabus. –

cevap

10

derleyici zorlar ve kopya atama operatörü (normalde, bu sadece kullanılıyorsa olur). Bunlar sırasıyla, v'un kopya kurucusu/ataması operatörünü çağırır. Ancak, std::vector<T>'un kopyalama işlemleri, gibi kopyalanamayan bir T için hatalı biçimlendirilmiştir. Bu yüzden hata.

Üye yalnızca std::unique_ptr olduğunda, sorun kopya işlemleri açıkça silinmiş olduğundan ve A varsayılan kopyalama işlemleri de silinmiş olduğundan, sorun oluşmaz. Açıkça kopya işlemleri silerseniz

Yani sorun çözüldü: Elbette

class __declspec(dllexport) A 
{ 
public: 
    A(const A&) = delete; 
    A& operator=(const A&) = delete; 
    vector<unique_ptr<int>> v; 
}; 

, sen kopyalama işlevini istemek eğer kendinizi de yardımcı olacağını tanımlayarak.

+1

Gerçekten "yanlış" değil, konuşmak için. 'vektör > 'nin kopya kurucusu silinmez; Sadece örnekleme başarısız olur. Sonuç olarak, 'A''nın kopya kurucusu da silinmez. Kopyalama için Ditto. –

+0

@ T.C. Elbette haklısın. Cevabı tekrar söyleyeceğim. – Angew

+2

'A (A &&) = varsayılan; A & operator = (A &&) = varsayılan; 'semantikleri hareket ettirir (eğer derleyiciniz kırılmamışsa, oh bekleyin, nm) ve kopyalayıcıları silme ihtiyacını ortadan kaldırır. – Yakk