[英]std::unique_ptr compiler error: Members of a derived class cannot access private members of a base class
當我嘗試編譯以下代碼時,我得到編譯器錯誤C2248 :
#include <list>
#include <memory>
using namespace std;
class data
{
public:
static data parse()
{
data d;
data::parse(d);
return d;
}
list<std::unique_ptr<data>> l;
private:
static void parse(data& node)
{ }
};
int main()
{
return 0;
}
為什么? 我怎樣才能解決這個問題?
注意:使用std::shared_ptr
而不是std::unique_ptr
我沒有問題。
您需要為您的類型提供移動操作:
data(data&& other)
: l(std::move(other.l))
{
}
data& operator=(data&& other)
{
l = std::move(other.l);
return *this;
}
而且,既然你已經添加了一個用戶聲明的構造函數,那么你還需要一個用戶聲明的默認構造函數:
data() { }
我的理解是,根據最終的C ++ 11語言標准,您的代碼是正確的。 Visual C ++沒有完全實現隱式生成移動操作的最終規范(從Visual C ++ 2012 RC開始)。 生成隱式移動操作的規范在標准化過程中很晚就改變了幾次。
如果您的類C
具有可移動但不可復制的任何數據成員,則Visual C ++將不會生成隱式移動構造函數或移動賦值運算符,並且隱式復制構造函數和復制賦值運算符都會因移動的存在而被抑制 - 只有數據成員。 換句話說,如果您不想要聚合僅移動類型,則必須自己為聚合類提供移動操作。
(至少,這是我對編譯器實驗的理解。)
首先,VC ++不會自動生成移動ctor並移動賦值運算符,這意味着您需要自己定義它們。
接下來,當您返回局部變量時,編譯器首先嘗試在實際執行復制它們的常規路徑之前移動它們。 但是,要做到這一點,它需要一個移動ctor。 由於它沒有那個,它嘗試通常的副本並通過生成的副本ctor自動調用std::list
的拷貝構造函數,后者又試圖調用其元素類型的拷貝ctor,它在std::unique_ptr
是私有的。 std::unique_ptr
的情況。
您需要定義一個合適的move ctor或一個不調用std::unique_ptr
的copy ctor的復制ctor(即,制作內容的深層副本)。
簡短回答:(特定於C ++ 11) list
項目必須是可復制的或可移動的。 unique_ptr
不能通過設計進行復制,但只要受控類型也可移動,它就是可移動的。
您的類型, data
不可移動,因為您尚未實現移動語義,並且編譯器沒有為您執行此操作。
實現移動語義,您可以在list
使用unique_ptr
:
data(ddata&&) {};
根據標准,編譯器將為您的類生成移動構造函數。 但是,VS10不支持這一點 - 這可能是你遇到的問題。
有關進一步參考,請參閱我關於CR的文章: 移動語義的規范實現
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.