Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> C++

Các cách copy vector trong C++

Có nhiều cách sao chép std::vector, mỗi cách có đặc điểm hiệu năng và ngữ nghĩa khác nhau.

1. Copy Constructor (Khuyến nghị nhất)

vector<int> v1 = {1,2,3,4};
vector<int> v2(v1);      // direct initialization
vector<int> v3 = v1;     // copy initialization
// Deep copy, O(N), exception-safe

2. Assignment Operator

vector<int> v2;
v2 = v1; // copy assignment, O(N), strong exception guarantee

3. assign() member function

vector<int> v2;
v2.assign(v1.begin(), v1.end()); // iterator range
v2.assign(5, 10);                // 5 copies of 10

4. std::copy + back_inserter

#include <algorithm>
#include <iterator>
vector<int> v2;
copy(v1.begin(), v1.end(), back_inserter(v2));
// Cần v2.reserve(v1.size()) trước để tránh reallocate nhiều lần

5. Range-based for + push_back

vector<int> v2;
v2.reserve(v1.size());
for (int x : v1) v2.push_back(x);

6. Constructor range (C++11)

vector<int> v2(v1.begin(), v1.end()); // từ iterator pair

So sánh hiệu năng & ngữ nghĩa

Phương phápĐộ phức tạpException safetyGhi chú
Copy ctor / operator=O(N)StrongCode ngắn, rõ nghĩa, tối ưu nhất (move nếu có)
assign(begin, end)O(N)BasicHữu ích khi v2 đã tồn tại, muốn clear rồi copy
std::copy + back_inserterO(N)BasicCần reserve thủ công, linh hoạt (có thể transform)
push_back loopO(N) amortizedBasicChậm hơn do check size mỗi lần, trừ khi reserve
Constructor rangeO(N)StrongTương tự copy ctor nhưng từ iterator bất kỳ

Shallow vs Deep Copy

  • Vector chứa kiểu giá trị (int, string, Point...) → Deep copy tự động (gọi copy ctor của phần tử).
  • Vector chứa con trỏ raw (vector<T*>) → Shallow copy (copy địa chỉ). Cần tự quản lý sở hữu – khuyến nghị dùng unique_ptr/shared_ptr.

Move Semantics (C++11) – "Copy" không tốn O(N)

vector<int> v1 = {1,2,3};
vector<int> v2 = std::move(v1); // v2 "cướp" tài nguyên v1, v1 rỗng
// O(1) – chỉ copy 3 con trỏ (data, size, capacity)

Khuyến nghị

  • Mặc định: vector<T> v2 = v1; hoặc vector<T> v2(v1);.
  • Cần copy một phần: vector<T> v2(v1.begin()+2, v1.end()-1);.
  • Cần transform khi copy: transform(v1.begin(), v1.end(), back_inserter(v2), func);.
  • Không còn cần v1: std::move(v1).