2011-11-02 22 views
5

Tôi đang cố gắng tạo một véc tơ loại bất khả tri trong C++ được phân biệt bằng hai thứ. Đầu tiên, nó phân bổ bộ nhớ trong chính đối tượng, ít nhất là cho đến một điểm nhất định, thay vì duy trì một mảng các đối tượng thực sự trên heap. Thứ hai, nó không thể sử dụng các bản sao chép/gán của C++, điều này dường như làm chậm mã và không cần thiết.Khi di chuyển/sao chép các cá thể đối tượng C++

Trong khi xem qua mã nguồn tôi duy trì trên máy tính của mình, tôi đã tìm thấy một lớp trong codebase của LLVM khá nhiều mô tả hoàn hảo những gì tôi đang tìm kiếm: SmallVector.h. Là tương đối mới đối với C++, tôi không hoàn toàn chắc chắn lý do tại sao một số quyết định thiết kế đã được thực hiện. Ví dụ: tại sao mảng được phân bổ theo điều khoản của U thay vì T? Nhận xét đưa ra một đầu mối:

Nếu T có một ctor hoặc dtor, chúng ta không muốn nó được tự động chạy, vì vậy chúng ta cần đại diện cho không gian như cái gì khác. Một mảng char sẽ hoạt động tốt, nhưng có thể không được căn chỉnh đầy đủ. Thay vào đó, chúng tôi sử dụng một số trường hợp công đoàn cho không gian, đảm bảo căn chỉnh tối đa.

U, tất nhiên, đề cập đến sự kết hợp sau đây:

union U { 
    double D; 
    long double LD; 
    long long L; 
    void *P; 
} FirstEl; 

Vì vậy, tôi đoán, đây là những câu hỏi thật sự của tôi: Tại sao bố trí một mảng của T ngụ ý rằng nhà xây dựng/hủy được gọi là? Có cách nào để di chuyển đối tượng C++ đối tượng xung quanh, tức là trong và ngoài của vector, mà không gọi những constructors/destructors? Tôi đoán tôi chỉ có thể sử dụng thực hiện SmallVector LLVM của, nhưng tôi ghét sử dụng mã mà không hiểu nó.

nhất, Duane

+0

'C++ 's sao chép/gán constructors, mà dường như làm chậm mã ...' Nó làm cho _correct_ mã, bởi vì họ _are_ cần thiết. Có một số lớp sẽ sụp đổ nếu chúng được bao giờ bị memcopied, và làm _not_ có một hàm tạo mặc định. –

Trả lời

3

Bạn nên xem xét máy móc cơ bản đằng sau thư viện chuẩn nhà phân bổ, giải quyết rất nhiều câu hỏi mà bạn có thể có!

Đây là nguyên tắc phân bổ cơ bản. Chúng tôi phân bổ bộ nhớ riêng biệt và xây dựng đối tượng. Trở ngại lớn nhất là, khi bạn quan sát, mà bộ nhớ cần được sắp xếp một cách chính xác cho các đối tượng:

// getting memory 
void * p = malloc(1000); // version 1, system's allocator 
char q[1000];    // automatic array, this is also memory :-) 

// constructing an object 
T * m_x1 = ::new (p) T; // default-initialized 
T * m_x2 = ::new (q) T(); // value-initialized 
T * m_x3 = ::new (q + sizeof(T)) T(1, 'a'); // some specific constructor 

// destroying the objects: 
m_x1->~T(); 
m_x2->~T(); 
m_x3->~T(); 

Để làm những gì bạn có trong tâm trí, bạn có thể lấy mảng char q mà tôi sử dụng và làm cho nó một thành viên của lớp học của bạn.Đó là, lớp luôn luôn mang theo xung quanh với nó một số bộ nhớ trong đó để xây dựng các đối tượng.

Việc xây dựng đối tượng thực tế được thực hiện với biểu thức mới vị trí toàn cầu. Nhớ lại rằng các đối tượng do đó xây dựng phải được tiêu huỷ bằng tay (đó sẽ là trách nhiệm của bạn).

Trình phân bổ thư viện chuẩn làm khá nhiều điều tương tự.

Tách phân bổ bộ nhớ và xây dựng đối tượng là trọng tâm của bất kỳ loại quản lý bộ nhớ nâng cao, lớp sở hữu trách nhiệm nào.

Lưu ý rằng khi đối tượng được xây dựng tại địa chỉ cụ thể, bạn không được di chuyển bộ nhớ xung quanh. Đối tượng có thể rất phụ thuộc vào vị trí của nó trong bộ nhớ! Cách duy nhất để di chuyển các đối tượng xung quanh là sao chép/di chuyển-xây dựng một đối tượng mới.

1

Tại sao bố trí một mảng của T ngụ ý rằng nhà xây dựng/hủy được gọi là?

Vì đó là nhiệm vụ tiêu chuẩn. Phân bổ một mảng của T có nghĩa là khởi tạo từng phần tử của nó. Lưu ý rằng trong C++ 11 các hạn chế liên kết cho char đã được thay đổi để "một mảng char hoạt động tốt" ngay bây giờ.

Có cách nào để di chuyển các thể hiện đối tượng C++ xung quanh, tức là vào và ra khỏi vectơ mà không gọi các hàm tạo/trình phá hủy này không?

Có, bằng phương tiện di chuyển-nhà thầu/nhà khai thác gán, cũng mới đối với C++ 11. Có một thư viện giả lập cho C++ 03 và cũng có các thùng chứa hỗ trợ di chuyển tại Boost.

+1

Lưu ý: Một mảng char được phân bổ _dynamically_ hoạt động cho tất cả các sắp xếp. Một mảng ký tự tự động có thể không. –

0

C++ 11 cũng có ngữ nghĩa di chuyển. Nếu bạn thực hiện một hàm tạo di chuyển trong lớp của bạn (nói Foo), std :: vector sẽ hoạt động tốt hơn nhiều.

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