2009-01-23 18 views

Trả lời

23

Để phân bổ trên stack, hoặc tuyên bố đối tượng của bạn như một địa phương biến bởi giá trị, hoặc bạn thực sự có thể sử dụng alloca để có được một con trỏ và sau đó sử dụng tại chỗ điều hành mới:

void *p = alloca(sizeof(Whatever)); 
new (p) Whatever(constructorArguments); 

Tuy nhiên, trong khi sử dụng alloca và tại chỗ mới đảm bảo rằng bộ nhớ được giải phóng khi trả lại, bạn bỏ cuộc gọi hủy tự động. Nếu bạn chỉ cố gắng đảm bảo rằng bộ nhớ được giải phóng khi thoát khỏi phạm vi, hãy xem xét sử dụng std::auto_ptr<T> hoặc một số loại con trỏ thông minh khác.

12

Jeffrey Hantin là khá chính xác mà bạn có thể sử dụng vị trí mới để tạo ra nó trên stack với alloca. Nhưng, nghiêm túc, tại sao ?! Thay vào đó, chỉ cần thực hiện:

class C { /* ... */ }; 

void func() { 
    C var; 
    C *ptr = &var; 

    // do whatever with ptr 
} 

Bây giờ bạn có con trỏ đến đối tượng được phân bổ trên ngăn xếp. Và, nó sẽ bị phá hủy đúng cách khi chức năng của bạn tồn tại.

+2

Ví dụ của bạn là chính xác những gì tôi muốn nói bằng cách khai báo biến đó dưới dạng giá trị cục bộ theo giá trị. –

+0

lưu ý: lớp phải có một hàm tạo rỗng được định nghĩa trong cpp, nếu bạn đã có một hàm tạo không rỗng được định nghĩa. – kevinf

+0

trường hợp sử dụng tôi đã có - nói 'C' có một phương thức' virtual' được ghi đè trong các lớp con 'C1' và' C2'. Sau đó, tôi có thể muốn làm 'C * ptr = tiêu chí? mới (alloca (sizeof (C1))) C1 (...): new (alloca (sizeof (C2))) C2 (...); ' – rampion

5

Bạn có thể làm:

Whatever* aWhatever = new (alloca(sizeof(Whatever))) Whatever; 

Bạn có thể sử dụng một lớp RAII để làm phá hủy Tôi cho rằng (EDIT: Xem thêm this other answer for more information on potential problems with this approach):

template <class TYPE> 
class RAII 
    { 
    public: 
     explicit RAII(TYPE* p) : ptr(p) {} 
     ~RAII() { ptr->~TYPE(); } 
     TYPE& operator*() const { return *ptr; } 
    private: 
     TYPE* ptr; 
    } 

void example() 
    { 
    RAII<Whatever> ptr = new (alloca(sizeof(Whatever))) Whatever; 
    } 

Bạn có thể sử dụng một macro để ẩn alloca.

Trân DaveF

2

Hãy cẩn thận khi sử dụng _alloca() với GCC

GCC có bug which makes _alloca() incompatible with SJLJ exception handling trong C++ (Dwarf2 được báo cáo là hoạt động chính xác). Khi một ngoại lệ được ném ra khỏi hàm phân bổ bộ nhớ, lỗi này gây ra sự tham nhũng ngăn xếp trước khi các trình phá hủy có thể chạy. Điều này có nghĩa là bất kỳ lớp RAII nào hoạt động trên (các) đối tượng được phân bổ đều phải chạy trong một hàm khác để hoạt động bình thường. Cách thích hợp để thực hiện nó trông giống như sau:

void AllocateAndDoSomething() 
{ 
    Foo* pFoo = reinterpret_cast<Foo*>(_alloca(sizeof(Foo))); 
    new (pFoo) Foo; 

    // WARNING: This will not work correctly! 
    // ScopedDestructor autoDestroy(pFoo); 
    // pFoo->DoSomething(); 

    // Instead, do like this: 
    DoSomething(pFoo); 
} 

void DoSomething(Foo* pFoo) 
{ 
    // Here, destruction will take place in a different call frame, where problems 
    // with _alloca() automatic management do not occur. 
    ScopedDestructor autoDestroy(pFoo); 
    pFoo->DoSomething(); 
} 
Các vấn đề liên quan