2017-04-06 146 views
0

我有以下程序 -C++移動的unique_ptr一個struct構件

#include <iostream> 
#include <memory> 

class Person 
{ 
    public: 
     Person(const std::string& name): 
     name(name) { } 

     ~Person() { std::cout << "Destroyed" << std::endl; } 

     std::string name; 
}; 

typedef struct _container 
{ 
    std::unique_ptr<Person> ptr; 
}CONTAINER; 

void func() 
{ 
    CONTAINER* c = static_cast<CONTAINER*>(malloc(sizeof(CONTAINER))); 
    std::unique_ptr<Person> p(new Person("FooBar")); 
    c->ptr = std::move(p); 
    std::cout << c->ptr->name << std::endl; 
} 


int main() 
{ 
    func(); 
    getchar(); 

    return 0; 
} 

該程序打印 「FooBar的」。我希望程序在func()返回時打印「銷燬」,但不會。有人可以幫我解釋爲什麼在這種情況下不會發生這種情況嗎?

回答

1

實際上,你已經得到了不確定的行爲在這裏。 你不能將一個malloc'd緩衝區轉換爲對象類型。構造函數永遠不會被調用,並且您的成員變量處於無效狀態。

你需要做的要麼:

void func() 
{ 
    CONTAINER c; 
    std::unique_ptr<Person> p(new Person("FooBar")); 
    c.ptr = std::move(p); 
    std::cout << c.ptr->name << std::endl; 
} 

或者

void func() 
{ 
    CONTAINER * c = new CONTAINER(); 
    std::unique_ptr<Person> p(new Person("FooBar")); 
    c->ptr = std::move(p); 
    std::cout << c->ptr->name << std::endl; 
    delete c; 
} 

,或者如果你真的想使用malloc - 你需要使用新的佈局,以獲得正確的行爲 - 但通常你不想這樣,所以我現在不會詳細說明...

2

您忘記在func()的末尾添加此行。

delete c; 

Here是測試(ideone)。

c是一個原始指針。這不是一個聰明的指針。 因此,您必須手動刪除它。

刪除c將自動刪除CONTAINER::ptr,因爲CONTAINER::ptr是一個唯一的指針。

但是,你自己有malloc,更正確的代碼可能是: -

c->~_container(); 

然後free(),但我不認爲它是需要在這種情況下,因爲CONTAINER不上堆。
(我從來沒有使用malloc,所以我不知道這部分。)

編輯:
我的解決方法是快速更新來解決一個問題。 (不打印「銷燬」)
另請參閱邁克爾安德森的解決方案。
它解決了另一個底層問題的OP代碼。 (malloc的)

EDIT2: Here是關於投放新說邁克爾·安德森提到一個很好的鏈接。
下面的代碼從連桿(帶小的修改)複製: -

int main(int argc, char* argv[]){ 
    const int NUMELEMENTS=20; 
    char *pBuffer = new char[NUMELEMENTS*sizeof(A)]; 
    //^^^ difference : your "CONTAINER" could be char[xxxx] (without new) 
    A *pA = (A*)pBuffer; 
    for(int i = 0; i < NUMELEMENTS; ++i) { 
    pA[i] = new (pA + i) A(); 
    } 
    printf("Buffer address: %x, Array address: %x\n", pBuffer, pA); 
    // dont forget to destroy! 
    for(int i = 0; i < NUMELEMENTS; ++i){ 
    pA[i].~A(); 
    } 
    delete[] pBuffer;//<--- no need to delete char[] if it is a stack variable 
    return 0; 
} 

如需更多詳細信息,請參見上面的鏈接(因爲我不想要更多的將它複製到這裏)。

這裏是另一個有用的鏈接:Using malloc in C++ is generally not recommended.

+0

啊,我明白了。由於malloc'd區域不是「智能」,因此程序不跟蹤「c」跟蹤跟蹤唯一指針範圍的方式。 –

+0

@Jai Prabhu是的,我認爲這是正確的。 – javaLover

+2

不好 - 比這更糟的是,將一個malloc'd緩衝區轉換爲具有構造函數的類型是未定義的行爲 - 並且該程序允許產生它喜歡的任何垃圾。 –