2010-03-20 48 views
14

memset đôi khi được sử dụng để khởi tạo dữ liệu trong một hàm tạo như ví dụ dưới đây. Nó có hoạt động nói chung không? Đó có phải là một ý tưởng hay không?memset để khởi tạo trong C++

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

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

Bạn có thể sử dụng phương pháp sau: http://stackoverflow.com/a/38103250/3223828 –

Trả lời

21

Không sử dụng memset. Đó là một sự tiếp quản từ C và sẽ không hoạt động trên những người không phải là POD. Cụ thể, sử dụng nó trên một lớp dẫn xuất có chứa bất kỳ hàm ảo nào - hoặc bất kỳ lớp nào có chứa một non-builtin - sẽ dẫn đến thảm họa.

C++ cung cấp một cú pháp cụ thể để khởi tạo:

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

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

Thành thật mà nói, tôi không chắc chắn, nhưng memset cũng có thể là một ý tưởng tồi trên diện rộng các điểm kể từ khi định dạng của họ là không xác định.

+1

Cũng có 'std :: fill' hoặc' std :: fill_n' nếu bạn cần "memset" một mảng (hoặc bất kỳ chuỗi nào khác) – jalf

+0

Đối với mảng trường hợp nó tốt hơn để làm 'str()'. GCC có vấn đề khởi tạo mảng char bởi một chuỗi chữ thông qua một thành viên-initializer, và nếu mảng không phải là một mảng char nó sẽ không làm việc ngay cả trong một trình biên dịch phù hợp tiêu chuẩn. str() 'sẽ luôn luôn vô hiệu hóa mảng. (tôi vừa gửi báo cáo lỗi: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43453) –

+0

@litb: Lưu ý và thay đổi ở trên. – rlbond

12

Đó là một ý tưởng tồi tệ. Bạn chỉ đang tromping dữ liệu, không chú ý đến cách các đối tượng nên được khởi tạo. Nếu lớp của bạn là ảo, bạn có khả năng quét sạch con trỏ vtable.

memset hoạt động trên dữ liệu thô, nhưng C++ không phải là dữ liệu thô. C++ tạo trừu tượng, vì vậy nếu bạn muốn an toàn, bạn sử dụng những trừu tượng đó. Sử dụng danh sách khởi tạo để khởi tạo thành viên.

Bạn thể làm điều đó với các loại POD:

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

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

Nhưng nếu bạn đang làm nó trên this, có nghĩa là bạn đang ở trong một nhà xây dựng người dùng định nghĩa và không còn đủ điều kiện như một loại POD . (Mặc dù nếu tất cả các thành viên của bạn là POD nó có thể làm việc, miễn là không chứa 0 như một giá trị bẫy. Tôi chắc chắn không chắc chắn nếu bất kỳ nguồn khác của hành vi không xác định đi vào chơi ở đây.)

+0

Loại 'nothing_fancy_here' của bạn không có hàm tạo không? Tôi không nghĩ rằng có bất kỳ sự khác biệt giữa những gì bạn đang gọi một loại POD, và lớp ví dụ OPs ... Cho dù bạn đang gọi 'memset' từ bên trong constructor hay không là không thích hợp. Nếu nó là ok trong ví dụ của bạn, nó là ok trong OP's. –

+0

@STingRay: Nó không có hàm tạo. Có lẽ '// ...' quá mở. – GManNickG

+0

Nó có một hàm tạo. Cấp nó là một no-op. Điểm về việc liệu có một nhà xây dựng được khai báo rõ ràng hay không là không liên quan. Điều quan trọng là, như bạn đã nói, cho dù cấu trúc/lớp (hoặc bất kỳ loại thành viên của nó ') có chức năng thành viên ảo. Nếu OP không khai báo một hàm tạo và gọi là 'memset' giống như bạn đã làm, thì không có sự khác biệt. Vì vậy, câu trả lời cuối cùng là: trong các ví dụ nhất định, về mặt kỹ thuật là * ok * để làm, nhưng như là một thực hành chung, chắc chắn không phải ... –

Các vấn đề liên quan