01/10/2018, 13:58
Chuyển code mảng động 2 chiều dạng C sang C++ (con trỏ)
Mình có 1 đoạn code cấp phát mảng động 2 chiều sau (ngôn ngữ C)
template <class T>
void allocMatrix(T** &matrix, int n, int m)
{
size_t pointerSize = n * sizeof(T*);
size_t storeSize = n * (size_t)m * sizeof(T);
void *buffer = calloc(pointerSize + storeSize, 1); //1
if (buffer == nullptr) return;
matrix = (T**)buffer;
T *data = matrix[0] = (T*)((char*)buffer + pointerSize); //2
for (int i = 0; i < n; ++i)
{
data += m;
matrix[i] = data;
}
}
Đoạn code trên dùng để cấp phát 1 vùng nhớ duy nhất chứa con trỏ và các phần tử trong ma trận (sách Kĩ Thuật Lập Trình - Trần Đan Thư)
Code trên có dùng hàm calloc
của C, bây giờ mình muốn chỉnh lại sang C++ (từ //1
đến //2
) như sau:
T *buffer = new T[pointerSize + storeSize];
if (buffer == nullptr) return;
matrix = (T**)buffer;
T *data = matrix[0] = buffer + pointerSize;
thì tính chất có giống với code gốc phía trên không mọi người. Mình có chạy qua nhiều test (đã thành công) nhưng vẫn muốn lên đây hỏi cho chắc. Cảm ơn mọi người.
Bài liên quan
code gốc đã là C++ rồi mà??
viết cái gì ko ai hiểu @_@
em chuyển code kia lại xài new sai rồi
T *buffer = new T[pointerSize + storeSize];
phải là
char *buffer = new char[pointerSize + storeSize];
nếu xài C++17 thì dùng
std::byte
thay chochar
nếu muốn kĩ hơn nữa thì em viết thêm cái cast cho đàng hoàng:
ý là em thấy code ban đầu khai báo void, rồi sau đó phải ép về kiểu T* nên em nghĩ là lúc đầu khai báo bằng T* để lúc sau khỏi cần ép kiểu
Muốn cho giống thì phải dùng
new(std::nothrow)
, dùng new thường sẽ bị văng exception khi ko thể cấp phát được.Vì sao phải cast 2 lần? Bởi vì chỉ có chuyển từ void* đi và đến là được xác định (defined).
em chưa rõ lắm đoạn cast 2 lần, anh giải thích cho em với
code trong sách khai báo là
em thấy ép kiểu 2 lần là
(T*)((char*)buffer...
nên định ban đầu sẽ choT *buffer = new (nothrow) T[pointerSize + storeSize];
để khỏi phải ép kiểu 2 lần.void*
có hai đặc tính:void*
giữ nguyên giá trị con trỏ.void*
không có phép tính.Cấp phát kiểu
T
ngay sẽ rất nguy hiểm vì phải chia trường hợp ứng với alignment của T. Phân tích dòng 6 sẽ thấy rằng phần dữ liệu phải nằm sau n con trỏ. Câu này nhiều nguy cơ dính unspecified do T có alignment chặt hơn char (C++) hoặc undefined do không phải là 1 byte © chiếu theo 6.3.2.3 N1256.Vậy hay nhất là xin cấp phát char rồi chỉ dùng
void*
làm trung gian như trên.