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

Truyền vector vào Constructor trong C++

Truyền std::vector vào constructor của lớp để khởi tạo thành viên dữ liệu. Có 3 cách chính tùy ý đồ sở hữu và hiệu năng.

1. Truyền bằng const reference + copy (An toàn, phổ biến)

class MyClass {
    vector<int> data_;
public:
    MyClass(const vector<int>& v) : data_(v) {} // copy
    // hoặc explicit MyClass(const vector<int>& v) : data_(v) {}
};
  • Gọi copy constructor của vector – deep copy O(N).
  • An toàn, caller giữ nguyên vector gốc.

2. Truyền bằng value + move (C++11 – Hiệu quả khi caller có temporary)

class MyClass {
    vector<int> data_;
public:
    MyClass(vector<int> v) : data_(std::move(v)) {} // move từ parameter
};
  • Caller: MyClass obj(vector<int>{1,2,3}); (temporary) → 1 move.
  • Caller: MyClass obj(myVec); (lvalue) → 1 copy vào param + 1 move vào member = 1 copy.
  • Tối ưu cho cả lvalue và rvalue.

3. Perfect Forwarding (C++11 – Linh hoạt nhất)

class MyClass {
    vector<int> data_;
public:
    template<typename Vec>
    MyClass(Vec&& v) : data_(std::forward<Vec>(v)) {}
};
  • Chấp nhận lvalue (copy) và rvalue (move) tự động.
  • Cẩn thận: template constructor có thể match mọi thứ – dùng enable_if hoặc concepts (C++20) để hạn chế.

Ví dụ đầy đủ (Cách 2 – Khuyến nghị)

#include <iostream>
#include <vector>
#include <utility> // move
using namespace std;

class VectorHolder {
    vector<int> vec_;
public:
    // Pass by value + move
    VectorHolder(vector<int> v) : vec_(std::move(v)) {}

    void show() const {
        for (int x : vec_) cout << x << ' ';
        cout << endl;
    }
};

int main() {
    vector<int> v = {7, 6, 5, 4};
    VectorHolder h1(v);           // lvalue -> copy + move
    VectorHolder h2(vector<int>{1,2,3}); // rvalue -> move + move (elided)
    VectorHolder h3({4,5,6});     // initializer_list -> vector temp -> move
    h1.show(); // 7 6 5 4
    h2.show(); // 1 2 3
    h3.show(); // 4 5 6
    return 0;
}

Kết quả

7 6 5 4
1 2 3
4 5 6

So sánh nhanh

CáchLvalue callerRvalue callerCode complexity
const ref + copy1 copy1 copyThấp
by value + move1 copy + 1 move1 move (elided)Thấp
Perfect forwarding1 copy1 moveCao (template)

Lưu ý

  • Nếu class chỉ cần xem vector (không lưu) → dùng const vector<T>& hoặc span<T> (C++20).
  • Nếu cần chia sẻ sở hữu → shared_ptr<vector<T>>.
  • Tránh truyền vector by value nếu không move vào member (gây copy thừa).