Tôi cho rằng bộ nhớ của bạn được căn chỉnh đủ cho T
. Bạn có thể muốn kiểm tra điều đó.
Vấn đề tiếp theo là ngoại lệ. Chúng ta thực sự nên viết hai phiên bản, một với khả năng xây dựng sẽ gây ra một ngoại lệ, và một không có.
Tôi sẽ viết phiên bản an toàn ngoại lệ.
template<class T, class...Args>
T* construct_n_exception_safe(std::size_t n, void* here, Args&&...args) {
auto ptr = [here](std::size_t i)->void*{
return static_cast<T*>(here)+i;
};
for(std::size_t i = 0; i < n; ++i) {
try {
new(ptr(i)) T(args...);
} catch(...) {
try {
for (auto j = i; j > 0; --j) {
ptr(j-1)->~T();
}
} catch (...) {
exit(-1);
}
throw;
}
}
return static_cast<T*>(here);
}
và không ngoại lệ phiên bản an toàn:
template<class T, class...Args>
T* construct_n_not_exception_safe(std::size_t n, void* here, Args&&...args) {
auto ptr = [here](std::size_t i)->void*{
return static_cast<T*>(here)+i;
};
for(std::size_t i = 0; i < n; ++i) {
new (ptr(i)) T(args...);
}
return static_cast<T*>(here);
}
Bạn có thể làm một hệ thống dựa trên thẻ-văn để chọn giữa chúng tùy thuộc vào nếu xây dựng T
từ Args&...
ném hay không. Nếu nó ném, và ->~T()
là không tầm thường, hãy sử dụng một ngoại lệ an toàn.
C++ 17 cho thấy một số chức năng mới để thực hiện chính xác các tác vụ này. Họ có thể xử lý các trường hợp góc của tôi không.
Nếu bạn đang cố gắng bắt chước new[]
và delete[]
, nếu T
có một dtor không tầm thường, bạn sẽ phải nhúng bao nhiêu T
bạn đã tạo trong khối.
Cách điển hình để thực hiện việc này là yêu cầu thêm phòng để đếm số mặt trước của khối. Tức là, hãy yêu cầu sizeof(T)*N+K
, trong đó K
có thể là sizeof(std::size_t)
.
Bây giờ trong trình mô phỏng new[]
, hãy nhập N
vào bit đầu tiên, sau đó gọi construct_n
trên khối ngay sau đó.
Trong delete[]
, trừ sizeof(std::size_t)
từ con trỏ được chuyển vào, đọc N
và sau đó phá hủy các đối tượng (từ phải sang trái để xây dựng trình tự gương).
Tất cả điều này sẽ cần cẩn thận try
- catch
.
Nếu, tuy nhiên, ~T()
là tầm thường, cả giả lập new[]
và delete[]
không lưu trữ thêm std::size_t
cũng như không đọc chúng.
(Lưu ý rằng đây là làm thế nào để thi đuanew[]
và delete[]
. Làm thế nào chính xác new[]
và delete[]
công việc là thực hiện phụ thuộc. Tôi chỉ phác thảo ra một cách để bạn có thể bắt chước họ, nó có thể không phù hợp với cách thức hoạt động trên hệ thống của bạn. Ví dụ, một số Abis có thể luôn luôn lưu trữ N
ngay cả khi ->~T()
là tầm thường, hoặc vô số các biến thể khác.)
theo ghi nhận của OP, bạn cũng có thể muốn kiểm tra để xây dựng tầm thường trước làm phiền với những điều trên.
Có phiên bản vị trí mới cho mảng ... nhưng có thể có sự cố liên kết. Là [this] (http://coliru.stacked-crooked.com/a/01699890c4ae1ac0) những gì bạn cần? – AndyG
@AndyG: Có thể không, bởi vì vị trí 'new []' sử dụng một số không gian để viết thông tin được sử dụng bởi 'delete []'. – einpoklum