Tôi đã tự hỏi về một cách có thể để làm cho bố trí bộ nhớ của một lớp có hiệu quả hơn trong mã templated. Theo như tôi biết, Tiêu chuẩn ủy nhiệm các thành viên dữ liệu của một lớp được đưa ra trong bộ nhớ theo thứ tự tuyên bố của họ. Có thể có khả năng đệm được thực hiện bởi trình biên dịch để căn chỉnh các thành viên dữ liệu thêm không cần thiết vào kích thước của lớp. Ý tưởng là sắp xếp lại các khai báo thành viên dữ liệu tại thời gian biên dịch để giảm thiểu sự đệm như vậy. Tôi đã làm một số tìm kiếm, nhưng không thể tìm thấy bất kỳ thông tin (hầu hết thời gian mọi người thảo luận về chỉ thị trình biên dịch đóng gói, mà không phải là khá giống như tôi nhìn thấy nó).Sắp xếp lại thời gian của các thành viên dữ liệu?
Trước tiên, hãy xem xét như sau (tầm thường, nhưng lặp đi lặp lại và xấu xí) mã (same code on ideone.com) (câu hỏi dưới mã, cảm thấy tự do để bỏ qua phải xuống cho họ): sản lượng
#include <iostream>
#include <cstdint>
namespace so
{
template <typename Ta, typename Tb, typename Tc, std::size_t =
((sizeof(Ta) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Tc))) ? 10 :
((sizeof(Ta) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Tb))) ? 11 :
((sizeof(Tb) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tc))) ? 20 :
((sizeof(Tb) >= sizeof(Tc)) && (sizeof(Tc) >= sizeof(Ta))) ? 21 :
((sizeof(Tc) >= sizeof(Ta)) && (sizeof(Ta) >= sizeof(Tb))) ? 30 :
((sizeof(Tc) >= sizeof(Tb)) && (sizeof(Tb) >= sizeof(Ta))) ? 31 : 0>
struct foo {};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 10>
{
Ta a;
Tb b;
Tc c;
foo(Ta _a, Tb _b, Tc _c) : a{_a}, b{_b}, c{_c} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 11>
{
Ta a;
Tc c;
Tb b;
foo(Ta _a, Tb _b, Tc _c) : a{_a}, c{_c}, b{_b} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 20>
{
Tb b;
Ta a;
Tc c;
foo(Ta _a, Tb _b, Tc _c) : b{_b}, a{_a}, c{_c} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 21>
{
Tb b;
Tc c;
Ta a;
foo(Ta _a, Tb _b, Tc _c) : b{_b}, c{_c}, a{_a} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 30>
{
Tc c;
Ta a;
Tb b;
foo(Ta _a, Tb _b, Tc _c) : c{_c}, a{_a}, b{_b} {}
};
template <typename Ta, typename Tb, typename Tc>
struct foo<Ta, Tb, Tc, 31>
{
Tc c;
Tb b;
Ta a;
foo(Ta _a, Tb _b, Tc _c) : c{_c}, b{_b}, a{_a} {}
};
template <typename Ta, typename Tb, typename Tc>
struct bar: public foo<Ta, Tb, Tc>
{
private:
using base = foo<Ta, Tb, Tc>;
public:
bar() = default;
using base::base;
};
template <typename Ta, typename Tb, typename Tc>
struct foobar
{
Ta a;
Tb b;
Tc c;
foobar() = default;
foobar(Ta _a, Tb _b, Tc _c) : a{_a}, b{_b}, c{_c} {}
};
} //namespace so
int main()
{
so::bar<std::uint16_t, std::uint32_t, std::uint16_t> bar{1, 2, 3};
so::foobar<std::uint16_t, std::uint32_t, std::uint16_t> foobar{1, 2, 3};
std::cout << sizeof(bar) << "\t" << sizeof(foobar) << std::endl;
std::cout << bar.a << " : " << bar.b << " : " << bar.c << std::endl;
std::cout << foobar.a << " : " << foobar.b << " : " << foobar.c << std::endl;
return (0);
}
Chương trình:
8 12
1 : 2 : 3
1 : 2 : 3
Câu hỏi:
- tôi s có một số, nổi tiếng trình biên dịch độc lập cách giải quyết điều đó (Tăng, có thể)?
- Nếu không, có một số chỉ thị dành riêng cho trình biên dịch sẽ tự động thực hiện điều đó (không có sự sai lệch dữ liệu như với
__atribute__((packed))
của GCC) không? - Điều này có thể được thực hiện theo cách tổng quát hơn (có thể sử dụng các mẫu variadic) không?
Cảm ơn bạn trước!
Gợi ý: Tôi tin rằng bạn có thể giải quyết vấn đề lặp lại bằng cách sử dụng thừa kế, mở cửa cho mẫu variadic, tuy nhiên điều này sẽ phụ thuộc nhiều vào trình biên dịch và mã có thể không thanh lịch (aka, bạn sẽ phải sử dụng một hàm để truy cập phần tử, chẳng hạn như 'get <0> (foo)'). Tôi cũng sẽ lưu ý rằng bạn chỉ xem xét kích thước và không phải là sự sắp xếp, trên một số kiến trúc 'double' dài 8 byte, nhưng được căn chỉnh trên 4 byte ranh giới, vì vậy tính toán của bạn có thể là phụ tối ưu. –
@MatthieuM. Bạn có nghĩa là loại thừa kế đệ quy khi chúng tôi unroll các gói tham số, và sử dụng một số loại 'get <>' để điều hướng thông qua nó? Liên kết có thể được xử lý với 'alignof()/std :: alignment_of <>', tôi tưởng tượng - cảm ơn vì đã chỉ ra điều đó. – lapk
Trên thực tế, vấn đề chính của tôi là tiếc là bạn không thể sử dụng mở rộng gói trong thuộc tính (gây phiền nhiễu) và có nhiều cách khác nhau để xử lý nó ... và sau đó tôi nhận ra rằng tôi đã xem xét những cách đó khi kiểm tra cách 'std :: tuple' đã được thực hiện và thay vì cố gắng triển khai lại chúng bằng cách sử dụng các thủ đoạn thừa kế, tôi có thể sử dụng lại một cách đơn giản 'std :: tuple': D –