2012-01-31 45 views
12

Tôi muốn sử dụng std::array từ C++ 11 làm trường của lớp của riêng tôi. Phải mất hai tham số mẫu (đầu tiên xác định loại dữ liệu, thứ hai xác định kích thước của một mảng).C++ 11 std :: mảng

Nhưng tôi biết thông số thứ hai chỉ trong hàm tạo. Tôi không quen với tiêu chuẩn C++ 11, nhưng tôi cho rằng không thể đặt tham số mẫu trong khi thực thi.

Có bất kỳ giải pháp thay thế nào cho std::array không? std::vector có lẽ hơi quá nhiều, vì tôi sẽ không bao giờ thay đổi kích thước của nó.

Trả lời

15

std::vector là điều đơn giản nhất để sử dụng; mặc dù như bạn nói, nó lãng phí một vài byte nếu bạn sẽ không bao giờ cần phải thay đổi kích thước nó.

std::unique_ptr<T[]>, được khởi tạo bằng kết quả của new T[size], sẽ là điều hiệu quả nhất; nó sẽ có cùng kích thước với con trỏ và sẽ xóa bộ nhớ được cấp cho bạn khi nó bị hủy. Nó không thể sao chép được, mặc dù; bạn sẽ cần phải cung cấp một hàm tạo bản sao cho lớp của bạn nếu bạn muốn nó có thể sao chép được. Nó cũng kém thuận tiện hơn std::arraystd::vector vì nó không có giao diện của vùng chứa tiêu chuẩn. Bạn có lẽ có thể viết một wrapper kiểu STL cho nó nếu bạn cần điều đó; nhưng tôi chỉ sử dụng std::vector trong trường hợp đó.

+3

Tôi sẽ nói sử dụng một std :: vector trên một unique_ptr , trước đây là tương thích với tất cả các chức năng thư viện chuẩn mà làm việc trên vòng lặp. Trong thực tế, toàn bộ điểm của std :: array là cung cấp một giao diện như vậy trên một mảng bình thường. –

+3

@ user1131467: Thật vậy, 'std :: vector' thuận tiện hơn nhiều; nhưng OP đã thể hiện một mối quan tâm về hiệu quả, vì vậy có lẽ tiết kiệm một vài byte là quan trọng. –

+0

Nếu bạn định viết một trình bao bọc kiểu STL, thì ít nhất nó cũng phải biết kích thước của nó. Bạn chỉ có thể không bận tâm về năng lực. – UncleBens

6

std :: mảng là khi bạn biết kích thước tĩnh tại thời gian biên dịch. Nếu bạn không biết cho đến khi chạy, hãy sử dụng std :: vector. Nếu bạn không thay đổi kích thước nó không có nhiều chi phí.

class Container 
{ 
    vector<T> v; 
    Container(int i) : v(i) { v.shrink_to_fit(); } 
}; 

Nếu bạn đang lo lắng về không gian:

http://en.cppreference.com/w/cpp/container/vector/shrink_to_fit

Không chắc chắn nếu có một cách để xây dựng các vector đã trimed. Nó dường như không được yêu cầu bởi các tiêu chuẩn được xây dựng trimed, mặc dù trong thực tế nhiều triển khai sẽ làm điều này.

BTW Bạn cũng có thể xây dựng một vectơ có vectơ (size_t N, T t) sẽ đặt mọi phần tử ban đầu thành t (không có phần tử này được xây dựng mặc định).

+0

IIRC, vectơ được xây dựng với * chính xác * dung lượng bạn yêu cầu. Không cần phải co lại sau đó.Mẹo sao chép và trao đổi để thu nhỏ một vector cũng dựa vào đó. – Xeo

+1

Điều thú vị là, đối với một số điểm chuẩn, không có chi phí nào cả và mã lệnh 'std :: vector' giống nhau, mã SSE được vector hóa như với mảng gốc (với g ++ ít nhất) –

+0

Tôi nghĩ rằng một mảng được phân bổ tại chỗ và vector được phân bổ động. –

11

Tôi không quen với tiêu chuẩn C++ 11, nhưng tôi cho rằng không thể đặt thông số mẫu trong khi thực thi.

Bạn không thể chuyển giá trị chỉ được biết trong thời gian chạy dưới dạng đối số mẫu ... mã được tạo bởi bản trình bày mẫu phải được tạo tại thời điểm biên dịch, do đó không thể phụ thuộc vào giá trị thời gian chạy.

Một số giải pháp có thể là tạo chuyên môn mẫu cho một số giá trị kích thước mảng phổ biến và sau đó là giá trị có thể có kích thước tối đa. Tôi nghĩ rằng mặc dù đó sẽ là một cách khá hiệu quả để làm việc.

Thành thật mà nói, trong trường hợp của bạn, std::vector rất có thể là giải pháp tốt nhất vì bạn chỉ cần gọi resize() trên vectơ để làm cho kích thước chính xác tại thời gian chạy thông qua phân bổ động.

+1

hoặc, thay vì 'resize()', sử dụng hàm tạo 'std :: vector (size_t n)'. –

+2

@phresnel: hoặc 'reserve' + một chuỗi' push_back'/'emplace_back' nếu không phải tất cả các mục của bạn đều giống nhau. –

3

Nếu bạn không biết kích thước của mảng cho đến khi chạy, sau đó bạn muốn sử dụng một std :: vector.

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