2012-04-30 22 views
12

Trong C++, trình phá hủy của đối tượng được gọi vào lúc đóng "}" cho khối nó được tạo ra, phải không? Vì vậy, điều này có nghĩa rằng nếu tôi có:C++ - Nếu một đối tượng được khai báo trong một vòng lặp, thì hàm hủy của nó có được gọi là ở cuối vòng lặp không?

while(some_condition) 
{ 
    SomeClass some_object; 
    some_object.someFunction(); 
    some_variable = some_object.some_member; 
} 

Sau đó destructor cho đối tượng được tạo ra trong một lần lặp của vòng lặp sẽ được gọi ở phần cuối của vòng lặp trước khi đối tượng khác được tạo ra, có đúng không?

Cảm ơn.

+0

bản sao có thể có của [vòng đời khai báo trong vòng lặp] (http://stackoverflow.com/questions/3768662/lifetime-of-declaration-within-a-loop) –

Trả lời

24

Có.

Nhưng bạn có thể tự mình thử nghiệm. Đây là một tính năng ngôn ngữ mà trình biên dịch có thể không nhận được sai.

#include <iostream> 

struct S { 
    S() { std::cout << "S::S()\n"; } 
    ~S() { std::cout << "S::~S()\n"; } 
}; 

int main() { 
    int i = 10; 
    while(i--) { 
    S s; 
    } 
} 
+0

Ngắn, ngọt, chính xác. == +1 – duffymo

+0

Tôi sẽ chấp nhận câu trả lời của bạn sau khi giới hạn thời gian chấp nhận cho phép tôi. –

+0

Tôi không biết, các trình biên dịch thực sự là tốt để hiểu sai ... :) +1 –

7

Hành vi quan sát được gọi là mỗi lần lặp lại.

Quy tắc thông thường về tối ưu hóa vẫn được áp dụng. Nếu trình biên dịch là thông minh và các đối tượng đơn giản sau đó trình biên dịch có thể làm bất cứ điều gì nó thích mà vẫn tạo ra những hành vi đúng, ví dụ .:

#include <iostream> 

struct foo { 
    int i; 
    foo() : i (-1) {} 
    ~foo() { i = 1; } 
}; 

int main() { 
    int i = 10; 
    while (--i) { 
    foo f; 
    std::cout << f.i; 
    } 
} 

Biên dịch để:

.Ltmp5: 
     .cfi_def_cfa_register %rbp 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     movl $_ZSt4cout, %edi 
     movl $-1, %esi 
     callq _ZNSolsEi 
     xorl %eax, %eax 
     popq %rbp 
     ret 

Tức là unrolled và không có dấu hiệu của destructor đó trong đó (mặc dù hành vi quan sát vẫn như cũ).

+3

Mã được tạo trên hệ thống của tôi nếu thành viên phức tạp hơn một chút so với chỉ một int và thay đổi tùy thuộc vào bộ đếm vòng lặp là khá thú vị - về cơ bản bạn kết thúc với bộ nhớ cho mỗi cá nhân instantiation của 'foo' sống bên trong nhị phân, được tính toán trước. – Flexo

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