2015-11-18 45 views
0
class Attr 
{ 
public: 
    Attr(); 
    Attr(const std::wstring& name) 
    { 
     ... 
    } 
}; 

class AttrDec : public Attr 
{ 
public: 
    AttrDec(Attr* attr) 
     :Attr() 
    { 
     _attr = attr; 
    } 
    AttrDec(Attr*&& attr) 
     :Attr() 
    { 
     _attr = std::move(attr); 
    } 

private: 
    Attr* _attr; 
}; 

class XAttr : public AttrDec 
{ 
public: 
    XAttr(const std::wstring& name) 
     :AttrDec(&Attr(name)) //HERE!!! 
    {} 
} 

在標記的位置我得到了一個警告:如何將右值變爲左值的指針?

非標準擴展使用:作爲左值右值類。

但我已經在類AttrDec中定義了移動構造函數!

我怎樣才能解決這個警告?

+2

它甚至意味着什麼移動指針?它沒有意義。它回落到簡單的複製..失去移動語義 –

+0

你不能使用臨時地址。一旦構造函數完成,它將被破壞。 –

+1

目前還不清楚你想要做什麼。'_attr'指向的數據的預期壽命是多少?在C++中,你必須關注數據的生命週期。如果你不知道,你的代碼將只會意外工作。你所看到的是編譯器說:「你把一個指針指向了一個幾乎爲零的東西,你可能搞砸了」。有很多方法可以讓它編譯*,但爲了讓它工作*你需要修復你的生命期問題。 – Yakk

回答

0

AttrDec(&Attr(name))正試圖採取臨時對象的地址。該地址的運營商只能在lvalues上使用。

你可以做的是改變XAttr

class XAttr : public AttrDec 
{ 
public: 
    XAttr(const std::wstring& name) 
     :AttrDec(new Attr(name)) // create a pointer here 
    {} 
}; 

然後在AttrDec擺脫rvalue構造。然後你需要添加一個析構函數到AttrDec並刪除其中的指針並添加一個拷貝構造函數來正確地複製指針,否則會出現內存泄漏。欲瞭解更多在具有資源mannaging類看:What is The Rule of Three?

+1

所以你的建議是泄漏資源來「解決」OP的問題? – Yakk

+0

你必須確保複製和移動構造函數/操作符被禁用或正確實施... –

+0

@Yakk我更新了答案。 – NathanOliver

2

解決這個正確的方法是按值來存儲,然後讓移動做它的事。移動指針不會移動的底層臨時值仍將走開,你就會有一個移動懸擺指針到無處:

class Attr 
{ 
public: 
    Attr(); 
    /*explicit depending on needs*/ Attr(const std::wstring& name) 
    { 
     ... 
    } 
} 

class AttrDec : public Attr 
{ 
public: 
    AttrDec(Attr attr) 
     :Attr() 
     , attr_(attr) 
    { 
    } 
    AttrDec(Attr&& attr) 
     :Attr() 
     , attr_(std::move(attr)) 
    { 
    } 

private: 
    Attr attr_; 
} 

class XAttr : public AttrDec 
{ 
public: 
    XAttr(const std::wstring& name) 
     : AttrDec(Attr(name)) //HERE!!! 
    {} 
} 
+0

只要沒有'Attr'的子類型,就可以。如果'Attr'具有子類型:'struct IntAttr:public Attr {...};',則會崩潰。 –

+0

使用值而不是點在這裏你失去了多態性 – rich

+0

這是不明顯的,OP實際上需要動態多態性。如果他這樣做,海事組織會更清潔地製作一個包含指向其內部指針的值語義的包裝器。 – Hurkyl

0

右值加到語言來防止物體的廣泛複製,創建臨時對象等等,但是指針本質上是簡單的整數,所以你不會在int上使用它們。 使用右值的開銷幾乎肯定會高於只複製指針。

0

您需要終身管理。

Aasuming上裝飾非視圖語義(裝飾擁有飾),並且無需值samantics(罕見的,如果你的基類是抽象的),這可能工作:

struct Attr { 
    Attr(); 
    Attr(const std::wstring& name) 
    {} 
}; 

struct AttrDec : Attr { 
    AttrDec(std::unique_ptr<Attr>&& attr){ 
    _attr = std::move(attr); 
    } 
private: 
    std::unique_ptr<Attr> _attr; 
}; 

struct XAttr : AttrDec { 
    XAttr(const std::wstring& name) 
    :AttrDec(std::make_unique<Attr>(name)) 
    {} 
}; 

如果您std缺乏make_unique(C++ 14),這裏是一個實現:

namespace notstd{ 
    template<class T,class...Args> 
    std::unique_ptr<T> make_unique(Args&&...args){ 
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 
    } 
} 

遠低於原始呼叫new清潔。

的主要區別是,上述makrs所有權明確。

使用共享指針,具有克隆支持的值語義指針或甚至查看指針的變體可以工作:最後一個選項要求XAttr在attr的第二個基類中提供獨立存儲。