2015-12-31 16 views
16

Tôi có một loại mà tôi đã xóa các nhà xây dựng bản sao từ, và tôi muốn có một vector loại này, vì vậy tôi cần phải tạo ra tất cả các yếu tố thông qua emplace_back. Tuy nhiên, emplace_back dường như yêu cầu một hàm tạo bản sao, vì trình biên dịch đưa ra một cảnh báo về việc không thể khởi tạo emplace_back vì hàm tạo bản sao đã bị xóa. Tại sao nó cần một nhà xây dựng bản sao? Tôi nghĩ rằng toàn bộ điểm của emplace_back là để xây dựng các vector mà không cần sao chép bất cứ điều gì. Tôi có thể có một số vector của các đối tượng không có hàm tạo bản sao không?Tại sao điều này không sử dụng emplace_back với công việc xây dựng bản sao đã bị xóa?

class MyType { 
public: 
    MyType(std::array<double, 6> a) {} 
    MyType(const MyType& that) = delete; 
}; 

int main() { 
    std::vector<MyType> v; 
    std::array<double, 6> a = {1,2,3,4,5,6}; 
    v.emplace_back(a); 
} 

Trình biên dịch là clang/llvm.

+0

http://cpp.sh/9v5w tại đây không hoạt động –

+0

ở đây cũng http://goo.gl/eLUPjR –

+0

'emplace_back' không cần hàm tạo bản sao nhưng khi dung lượng của vectơ không đủ để lưu trữ phần tử mới, vector cần phải phân bổ lại phần tử của nó, điều này đòi hỏi hàm tạo bản sao/di chuyển. Bằng cách xóa hàm tạo bản sao, bạn cũng ngăn chặn nó tạo ra hàm khởi tạo di chuyển mặc định. Trong trường hợp này, khai báo một hàm tạo di chuyển có thể làm việc – Danh

Trả lời

20

Khi bộ nhớ trong của vector phát triển, cần phải di chuyển các phần tử từ bộ nhớ cũ sang bộ nhớ mới. Bằng cách xóa hàm tạo bản sao, bạn cũng ngăn chặn nó tạo ra hàm khởi tạo di chuyển mặc định.

9

Để có thể gọi emplace_back, loại của bạn phải là EmplaceConstructible hoặc MoveInsertible. Bạn cần phải cung cấp một hàm khởi tạo cho lớp của bạn nếu bạn đã xóa hàm tạo bản sao. (Kiểm tra this cho các yêu cầu của emplace_back)

MyType(MyType &&a) {/*code*/} //move constructor 
0

Nếu bạn cố gắng chạy mã này:

// Example program 
#include <iostream> 
#include <string> 
#include <array> 
#include <vector> 
class MyType { 
public: 
    MyType(std::array<double, 6> a) { 
     std::cout<< "constructed from array\n"; 
     } 
    MyType(const MyType& that){ 
      std::cout<< "copy\n"; 
    } 

    MyType(MyType&& that){ 
      std::cout<< "move\n"; 
    } 
}; 

int main() { 
    std::vector<MyType> v; 
    std::array<double, 6> a = {1,2,3,4,5,6}; 
    v.emplace_back(a); 
} 

Bạn sẽ nhận được kết quả sau:

xây dựng từ mảng

Live Demo

Rõ ràng là chỉ cần constructor từ std::Array được gọi. Vì vậy, không cần cho copy constructor. Nhưng trong cùng một thời điểm nếu bạn deletedcopy constructor, trình biên dịch sẽ gây ra lỗi (ít nhất là trên hai trình biên dịch tôi đã thử firstsecond). Tôi nghĩ rằng một số trình biên dịch sẽ kiểm tra sự tồn tại của copy constructor khi sử dụng emplace_back ngay cả khi nó không cần thiết trong trường hợp thực tế này trong khi những người khác thì không. Tôi không biết tiêu chuẩn ở đây là gì (trình biên dịch nào là đúng hay sai).

+1

Vấn đề là 'emplace_back' có thể làm cho vectơ phát triển, cần các đối tượng bên trong để di chuyển được. Và vì 'MyType' có một hàm tạo bản sao do người dùng khai báo, nên không có hàm khởi tạo nào được tạo và lớp không thể sao chép cũng như không thể di chuyển được. – Angew

+1

nhưng ít nhất trong trường hợp này không có bản sao hoặc di chuyển được gọi là .. vậy sự khác biệt là gì? –

+0

@HumamHelfawi Nó có thể được yêu cầu cuối cùng. Điều đó có nghĩa là có một số mã sẽ ở đó để xử lý trường hợp đó. Và cho rằng hoặc là constructor di chuyển và constructor sao chép phải có mặt tại thời gian biên dịch. – bashrc

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