8

vector<T> có một constructor mà mất kích thước của vector, và như xa như tôi biết nó là rõ ràng, có thể được chứng minh bằng thực tế là đoạn mã sau thất bại trong việc biên dịchChuyển đổi ngầm định từ int sang vectơ?

void f(std::vector<int> v); 
int main() 
{ 
    f(5); 
} 

Những gì tôi không thể hiểu và đang yêu cầu bạn giải thích là tại sao đoạn mã sau biên dịch

std::vector<std::vector<int>> graph(5, 5); 

nó không chỉ biên dịch, nó thực sự thay đổi kích thước đồ thị đến 5 và đặt từng yếu tố để một vector trong số năm số không, tức là không giống như sẽ là mã tôi thường viết:

std::vector<std::vector<int>> graph(5, std::vector<int>(5)); 

Làm cách nào? Tại sao?

Compiler: MSVC10.0


OK, dường như đó là một lỗi MSVC (chưa nhau). Nếu ai đó có thể xây dựng trên lỗi trong câu trả lời (tức là tóm tắt các trường hợp lỗi được sao chép) Tôi sẽ sẵn sàng chấp nhận nó

+4

Điều này (đúng) không biên dịch trên GCC 4.7. Tuy nhiên, một sự khác biệt phi tiêu chuẩn của MSVC++. Họ có lẽ chỉ quên đánh dấu hàm khởi tạo 'tường minh', bạn có thể khai thác trong '' để kiểm tra điều đó. – syam

+0

@syam: Tôi rất vui khi nhiệt nó không biên dịch trên GCC, nhưng điều thực sự kỳ lạ là ví dụ đầu tiên biên dịch trên MSCV, trong khi cái kia thì không. Đó là điều thực sự kỳ lạ –

+0

@ArmenTsirunyan Không biên dịch trên VS2012; thông báo lỗi nói rằng hàm tạo là 'rõ ràng ' – Praetorian

Trả lời

7

Nó không thực sự là một lỗi. Câu hỏi đặt ra là điều gì có thể sai khi cho phép đoạn mã thứ hai trong khi mã đầu tiên không biên dịch?

Vấn đề là trong khi có vẻ như rõ ràng cho bạn những gì constructor bạn muốn gọi khi bạn làm:

std::vector<std::vector<int>> graph(5, 5); 

nó không phải là quá rõ ràng đối với trình biên dịch. Đặc biệt có hai quá tải nhà xây dựng có khả năng có thể chấp nhận đối số:

vector(size_type,const T& value = T()); 

template <typename InputIterator> 
vector(InputIterator first, InputIterator last); 

Người đầu tiên đòi hỏi sự chuyển đổi của 5-size_type (đó là unsigned), trong khi thứ hai là một trận đấu hoàn hảo, do đó sẽ là một trình biên dịch đã chọn ...

...nhưng trình biên dịch đòi hỏi sự quá tải thứ hai, nếu suy luận kiểu InputIterator là cư xử không thể thiếu như thể nó là một lời kêu gọi:

vector(static_cast<size_type>(first),static_cast<T>(last)) 

gì tiêu chuẩn C++ 03 có hiệu quả ủy nhiệm là đối số thứ hai là rõ ràng được chuyển đổi từ loại gốc int thành loại đích std::vector<int>. Bởi vì chuyển đổi rõ ràng bạn nhận được lỗi.

Chuẩn C++ 11 thay đổi từ ngữ để sử dụng SFINAE để vô hiệu hóa hàm tạo lặp nếu đối số không thực sự là trình lặp đầu vào, vì vậy trong trình biên dịch C++ 11 mã sẽ bị từ chối (có thể là lý do một số đã tuyên bố đây là một lỗi).

-4

std :: vector < int> có hàm tạo chấp nhận size_type và const int &. Đây là hàm khởi tạo mà tôi mong muốn được gọi trong trường hợp này, khởi tạo vectơ để có 5 int, mỗi giá trị có giá trị 5.

+3

Như bạn có thể đọc rõ ràng trong câu hỏi của tôi, nó * không * –

+0

@ArmenTsirunyan Trình biên dịch lỗi. – selalerer

+0

Trong trường hợp đó câu trả lời của bạn không có ý nghĩa –

1

Đây thực sự là phần mở rộng chứ không phải lỗi.

Hàm khởi tạo được gọi là hàm nhận hai trình lặp (nhưng thực sự, chữ ký sẽ khớp với hai tham số của cùng một loại); sau đó nó gọi một chuyên môn hóa khi hai trình vòng lặp thực sự là int, trong đó xây dựng một cách rõ ràng value_type bằng cách sử dụng giá trị end và điền vào vectơ với begin các bản sao của nó.

+0

Tôi không nghĩ rằng tôi hiểu ... int có nghĩa là gì như một iterator? –

+0

@ArmenTsirunyan: 'std :: vector' có một hàm tạo bắt đầu và kết thúc. Nó được định nghĩa là một cái gì đó giống như 'template vectơ (_It đầu tiên, _It last)', khớp với lời gọi của bạn.Sau đó nó gọi vào một hàm với các tình trạng quá tải khác nhau dựa trên kiểu '_It', một trong những quá tải xử lý trường hợp' 'It' là một 'int'. –

+0

Để trả lời câu hỏi của bạn, đó là __not__ một trình lặp, nhưng mã xử lý trường hợp bạn cho nó một int. –

2

Đối với tôi nó có vẻ như nó đang gọi constructor này:

template <class InputIterator> 
vector (InputIterator first, InputIterator last, 
    const allocator_type& alloc = allocator_type()); 

Tôi không chắc chắn nơi explicit đi vào nó, bởi vì các nhà xây dựng có nhiều tham số. Nó không tự động đúc từ một int đến một vector.

+0

Tiêu chuẩn nghiêm cấm sử dụng hàm tạo hai vòng lặp khi hàm tạo khác cũng có thể là một kết hợp phù hợp. –

+0

Tôi không nghĩ rằng tôi hiểu ... Làm thế nào là int một iterator đầu vào? –

+0

'InputIterator' chỉ là tham số mẫu - nó có thể là bất kỳ loại nào. –

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