2015-01-13 14 views
5

Đây là câu hỏi C++ 11 cụ thể. Giả sử tôi có một véc tơ std::vector<T> v đã được sử dụng và tôi muốn đổi kích thước thành n các phần tử được khởi tạo với giá trị hiện tại T val. (Usecase điển hình: vector là thành viên của một thể hiện đang được tái chế).Là std :: vector <T> :: thay đổi kích cỡ (n, val) đủ để khởi tạo?

Ưu điểm/nhược điểm của các cách sau là gì và hiệu quả nhất là gì?

1) Có phải std::vector<T>::resize(n, val) đủ để khởi tạo không?

v.clear(); 
v.resize(n, val); 

2) Nếu không, thì tôi cho rằng điều sau là đúng?

v.clear(); 
v.resize(n); 
std::fill(v.begin(), v.end(), val); 

3) Làm thế nào để hoán đổi?

v.swap(std::vector<T>(n, val)); 
+1

Nếu đây là một bản sao, xin vui lòng liên kết đến các giải pháp, tôi sẽ bỏ phiếu cho đóng cửa nó. – Sheljohn

+0

Tại sao bạn muốn đổi kích thước? Để giải phóng bộ nhớ? – edmz

+0

@black Trường hợp điển hình: đây là một thành viên cấp lớp và tôi đang tái chế bản sao. – Sheljohn

Trả lời

5

(4)

std::fill(v.begin(), std::min(v.begin() + n, v.end()), val); 
v.resize(n, val); 

Nếu T có hành vi phân công phù hợp mà ít nhất là rẻ hơn so với xây dựng một hình mới, sau đó sử dụng (4). Đây là trường hợp cho T = int (gán và cấu trúc giống nhau) và T = std :: string (gán có thể nhanh hơn xây dựng, vì nó có thể sử dụng bộ đệm hiện có).

Nếu T có cùng chi phí chuyển nhượng và xây dựng (ví dụ T = int), thì (1) cũng có thể được sử dụng để làm rõ mà không làm mất hiệu suất.

Nếu T không thể được chỉ định hoặc, đối với một số lý do, ấn định là tốn kém hơn xây dựng (hiếm) sau đó sử dụng (1)

(1) có thể được đơn giản hóa bằng cách sử dụng v.assign(n, val); (thanh danh cho @ Casey)

Tôi không biết liệu (4) có hiệu quả như nhau hay không bằng cách sử dụng assign. Tôi không biết nếu gán sẽ (mỉa mai, cho tên) gán các yếu tố mới cho những yếu tố hiện có, hoặc xây dựng chúng một lần nữa.

Chỉnh sửa: Có thể cải thiện thành (4) mà tôi chưa thử nghiệm. Nó có thể tránh được việc sao chép/di chuyển trong khi thay đổi dung lượng vector.

if (n <= v.capacity()) 
{ 
    std::fill(v.begin(), std::min(v.begin() + n, v.end()), val); 
    v.resize(n, val); 
} 
else 
{ 
    v.assign(n, val); 
} 
+0

Tôi đoán 4 chỉ thuận lợi nếu n lớn hơn kích thước hiện tại? – Sheljohn

+0

@ Sh3ljohn Cũng phát hiện ra, tôi đã cập nhật (4) –

+0

Có thể 'điền' ghi vượt quá' v.end() 'nếu n> kích thước cũ ?? –

3

(1) là đủ. (3) cũng hoạt động. Sự khác biệt là (1) không giải phóng bộ nhớ nếu kích thước mới nhỏ hơn hiện tại. (3) luôn phân bổ bộ nhớ mới và xóa bộ nhớ cũ.

(2) chậm hơn (1) nói chung, vì nó mặc định đầu tiên xây dựng các phần tử, sau đó gán chúng. Nó thậm chí có thể không biên dịch nếu T không phải là cấu hình mặc định.

+0

Tốt :) Tôi đoán thực hành và thử nghiệm _ad hoc_ sẽ xác định giữa (1) và (3) tùy thuộc vào các trường hợp. – Sheljohn

+1

Tôi sẽ nói 3 là hiệu suất tồi tệ nhất, nếu T là đơn giản. –

3

Cho phép chia nhỏ nó để hiển thị sự khác biệt giữa mỗi loại. Tôi sẽ sử dụng n là kích thước mới, m là kích thước cũ.

1.

v.clear();//keeps the same buffer, but calls the destructor on all the values 
v.resize(n, val);//only makes a new buffer if the value is bigger, does no moves. 

2.

v.clear();//keeps the same buffer, but calls the destructor on all the values 
v.resize(n);//initializes all the values to default 
std::fill(v.begin(), v.end(), val);//initializes all the values again to the new value 

3.

v.swap(std::vector<T>(n, val));//calls destructor on all values in v, cannot reuse the buffer, initializes all the values to the new value 

Sự khác biệt là tinh tế nhưng thực. 1 có thể (nhưng không phải là bảo đảm) tái sử dụng bộ đệm, có thể tiết kiệm chi phí bộ nhớ. 2 là giống như 1 nhưng không tái khởi động lại. 3 là giống như 1 nhưng nó không thể tái sử dụng bộ đệm.

Cá nhân tôi nghĩ rằng sự khác biệt giữa ba quá tinh tế đối với vấn đề trong hầu hết các trường hợp và 1 là dễ đọc nhất.

+0

Rất tốt và cảm ơn ý kiến ​​cá nhân của bạn về 1 so với 3 :) – Sheljohn

+0

1 IS được đảm bảo sử dụng lại bộ đệm. –

+0

@NeilKirk iff n <= m, không được chỉ định trong mã. Nếu đó là trường hợp, sau đó ông không nên làm thay đổi kích cỡ, như phân công có thể được nhanh hơn phá hủy và reinitialization. – IdeaHat

8

Tại sao không sử dụng giao diện được thiết kế cho công việc này chính xác?

v.assign(n, val); 

Documentation Here

+0

Bạn có biết chức năng này có được đảm bảo sử dụng toán tử gán trên bất kỳ phần tử nào đã tồn tại trong vectơ không? –

+0

Việc triển khai tùy thuộc vào người triển khai thư viện. Tiêu chuẩn không chỉ rõ cách nó phải hoạt động. Tôi hy vọng nó sẽ sử dụng nhiệm vụ trên các mục hiện có, xây dựng bản sao tại chỗ trên các bản mới và nếu vectơ co ​​lại do đó, phá hủy tại chỗ. –

+0

Nếu nó không được đảm bảo thì nó có thể không phải là cách hiệu quả nhất. –

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