2010-03-20 36 views
14

memset有時用於像下面的示例一樣在構造函數中初始化數據。它一般工作嗎?一般來說這是個好主意嗎?用於在C++中初始化的memset

class A { 
public: 
    A(); 
private: 
    int a; 
    float f; 
    char str[35]; 
    long *lp; 
}; 

A::A() 
{ 
    memset(this, 0, sizeof(*this)); 
} 
+0

您可以使用以下方法:http://stackoverflow.com/a/38103250/3223828 – 2016-06-29 15:21:42

回答

21

請勿使用memset。這是C的延期,不適用於非POD。具體而言,在包含任何虛函數的派生類(或任何包含非內建函數的類)上使用它將導致災難。

C++提供了一個特定的語法進行初始化:

class A { 
public: 
    A(); 
private: 
    int a; 
    float f; 
    char str[35]; 
    long *lp; 
}; 

A::A() 
    : a(0), f(0), str(), lp(NULL) 
{ 
} 

說實話,我不知道,但memset也可能是浮動點是一個壞主意,因爲它們的格式是不確定的。

+1

如果你需要「memset」一個數組(或任何其他序列),還有'std :: fill'或'std :: fill_n' – jalf 2010-03-20 02:53:42

+0

對於數組最好是使用'str()'。GCC在通過成員初始化程序初始化字符串時遇到問題,如果數組不是一個字符數組,它甚至不會在標準的符合編譯器中工作。 str()'將始終使數組無效(我剛剛提交了一個錯誤報告:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43453) – 2010-03-20 03:07:25

+0

@litb:注意到並在上面進行了更改。 – rlbond 2010-03-20 16:16:00

12

這是一個可怕的主意。你只是在對數據進行拼湊,不理會對象應該如何初始化。如果你的課是虛擬的,你也可能會消滅vtable指針。

memset適用於原始數據,但C++不是原始數據。 C++創建抽象,所以如果你想要安全,你可以使用這些抽象。使用初始化程序列表來初始化成員。

可以它做POD類型:

struct nothing_fancy_here 
{ 
    bool b; 
    int i; 
    void* p; 
}; 

nothing_fancy_here x; 
memset(&x, 0, sizeof(x)); 

但是,如果你這樣做是對this,這意味着你在一個用戶定義的構造函數,並且不再有資格作爲一個POD類型。 (雖然如果你的所有成員都是POD,它可能會工作,只要沒有0作爲陷阱值,我確定不確定是否有其他來源的未定義行爲在這裏發揮作用。)

+0

您的'nothing_fancy_here'類型是否也有構造函數?我認爲你在調用POD類型和OPs示例類之間沒有區別......不管你是否在構造函數中調用memset,都是無關緊要的。如果在你的例子中沒關係,在OP中沒關係。 – 2010-03-20 02:34:38

+0

@STingRay:它沒有構造函數。也許'// ...'太開放了。 – GManNickG 2010-03-20 02:39:34

+0

它確實有一個構造函數。授予它是一個沒有操作。關於是否存在明確聲明的構造函數的觀點是無關緊要的。正如你所說,重要的是,struct/class(或其任何成員的類型)是否具有虛擬成員函數。如果OP沒有聲明構造函數,並像以前一樣調用memset,則沒有區別。所以最終的答案是:在給定的例子中,它在技術上是可以做的,但作爲一般的做法,當然不是...... – 2010-03-20 02:47:48