2017-04-05 26 views
9

Tôi có một số hành vi kỳ lạ trên std :: vector với rvalues ​​thêm:С ++ 11 vector làm bản sao trên rvalue

#include <iostream> 
#include <vector> 

class A { 
public: 
    A():i_{5}{std::cout << "default" << std::endl;} 
    A(const A &data) { std::cout << "copied!" << std::endl; } 
    A(A &&data) {  std::cout << "moved " << std::endl; } 
    int i_; 
}; 

int main(int argc, char *argv[]) { 
    std::vector<A> datavec; 
    datavec.push_back(A{}); 
    datavec.push_back(A{}); 
    return 0; 
} 

đầu ra là:

default 
moved 
default 
moved 
copied! 

Vì vậy, vector vẫn tạo ra các bản sao của A , tôi càng đẩy nhiều - tôi càng nhận được nhiều bản sao hơn. Tuy nhiên, nếu tôi thay thế hàm khởi tạo bằng mặc định A (A & & dữ liệu) = mặc định; hoặc xóa hàm tạo bản sao với A (const A & dữ liệu) = xóa; Tôi nhận được kết quả đúng khi không có bản sao nào được thực hiện. Tôi cũng không có bản sao nếu lần đầu tiên tôi gọi datavec.reserve với đủ kích thước. tôi sử dụng gcc phiên bản 5.4.0 không có đối số cụ thể

g++ -std=c++11 -o main ../main.cpp 

Bạn đã có bất kỳ suy nghĩ về lý do tại sao vector làm cho các bản sao của rvalues ​​rõ ràng? Tôi hy vọng nó không phải là một số lỗi của STL

+1

Câu hỏi hay, câu trả lời hay và vị trí trùng lặp tuyệt vời. – Bathsheba

Trả lời

12

std::vector đang sao chép các phần tử của bạn trong thời gian phân bổ lại bộ đệm bên trong. Nó được chọn để sao chép thay vì di chuyển bởi vì constructor di chuyển của bạn không được đánh dấu noexcept. Đang đánh dấu nó ...

A(A &&) noexcept {  std::cout << "moved " << std::endl; } 

... sẽ khắc phục sự cố.

Telling trình biên dịch rằng di chuyển của bạn constructor sẽ không ném cho phép thực hiện std::vector 's để di chuyển trong phân bổ lại nội bộ, hoàn thành các ngoại lệ đảm bảo yêu cầu của tiêu chuẩn ++ C.

Ngoài ra, bạn có thể std::vector::reserve vùng chứa của mình trước để ngăn chặn sự phát triển của bộ đệm trong.

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