2010-05-25 40 views
5

Đoạn mã sau đưa ra cảnh báo:Cảnh báo "đối tượng tạm thời" - có phải là tôi hoặc trình biên dịch không?

[C++ Warning] foo.cpp(70): W8030 Temporary used for parameter '_Val' in call to 'std::vector<Base *,std::allocator<Base *> >::push_back(Base * const &)' 

.. trên dòng được chỉ định.

class Base 
{ 
}; 

class Derived: public Base 
{ 
public: 
Derived() // << warning disappears if constructor is removed! 
{ 
}; 
}; 

std::vector<Base*> list1; 
list1.push_back(new Base); 
list1.push_back(new Derived); // << Warning on this line! 

Compiler là Codegear C++ Builder 2007.

Nhưng kỳ lạ, nếu các nhà xây dựng cho nguồn gốc bị xóa, cảnh báo sẽ biến mất ... Có tôi hay trình biên dịch?

EDIT: Cách duy nhất tôi đã tìm thấy để loại bỏ các cảnh báo là một cái gì đó tương tự như sau:

Derived * d; 
list1.push_back(d = new Derived); // << No warning now... 
+0

Không cảnh báo mã này với gcc. – kriss

+0

Đó có thể không phải là * tất cả * mã. Do Base và Derived có các hàm tạo (các trình tạo không biên dịch)? –

+0

@MadKeithV - cho hoặc lấy #include , đó là TẤT CẢ mã. Tôi bắt đầu với một trường hợp phức tạp hơn nhiều và cắt nó xuống xương trần cho thấy vấn đề ở trên. – Roddy

Trả lời

2

Simple thử:

list1.push_back(new Derived()); 

tôi sợ có cái gì đó về POD (với các nhà thầu tầm thường) và không phải POD đang diễn ra ở đây.

EDIT:

Cho rằng mã biên dịch tốt với gcc.3.4.2 (--pedantic) Tôi có thể nói đó là một trình biên dịch không minh bạch. Tôi đang nghiêng về phía giải thích MarkB, tức là trình biên dịch tạo tạm thời ngay cả khi tôi không hiểu tại sao nó sẽ được yêu cầu và sau đó phàn nàn khi gán nó cho const& ... nhưng tôi vẫn còn lúng túng.

+0

thử tốt, nhưng không có sự khác biệt! – Roddy

+0

Thật khó chịu vì tôi không có trình biên dịch tiện dụng để thử nghiệm với nó:/Thật kỳ lạ khi cảnh báo tương tự không được tạo cho 'Base': hoặc có lẽ bởi vì' Base' không có một hàm tạo do người dùng định nghĩa? –

+0

Cơ sở đã có một hàm tạo do người dùng định nghĩa, nhưng tôi đã cắt nó ra vì nó không tạo ra sự khác biệt nào cho vấn đề. tức là, bằng cách sử dụng 'cơ sở mới' không bao giờ đưa ra một cảnh báo ... – Roddy

1

Kể từ list1 là một vector của Base*, các push_back chức năng trong danh sách sẽ mong đợi một tham số có kiểu Base* const&, trong khi mới của bạn được cung cấp Derived*. Để vượt qua tham chiếu (nếu cần trong push_back) trình biên dịch cần một đối tượng thực sự của kiểu tham chiếu, trong trường hợp này là Base*. Có một chuyển đổi tiềm ẩn có sẵn từ Derived* thành Base* mà trình biên dịch sử dụng để tạo đối tượng tạm thời của loại Base* để chuyển vào push_back và trình biên dịch cảnh báo bạn rằng nó đang tạo tạm thời này.

Lý do nó hoạt động khi bạn gán nó vào một biến là có không còn là một ẩn tạm thời cần thiết:. Nó ngầm có thể chuyển đổi các biến có tên để Base* ngầm và thông qua đó tham khảo trong

Tôi nghĩ bạn có thể im lặng cảnh báo này bằng cách nói push_back để điều trị con trỏ như một Base*:

list1.push_back(static_cast<Base*>(new Derived));

+0

Hmm. Các diễn viên không thay đổi mọi thứ, nhưng tôi thấy những gì bạn đang nói. Tuy nhiên, tôi vẫn không chắc chắn về sự khác biệt giữa hai chuyển đổi tiềm ẩn. – Roddy

+0

OK, vậy tại sao sự hiện diện của vấn đề hàm tạo Derived() ...? – Roddy

+0

Tôi đã tự hỏi về điều đó nhưng nó không có ý nghĩa với tôi. Nếu 'Derived *' được chuyển đổi hoàn toàn thành 'Base *' (như trường hợp) thì tại sao một 'Base *' và 'Derived *' lại được xử lý khác nhau? Tôi không thấy sự cần thiết phải tạo tạm thời từ 'Derived *' thành 'Base * const &' (btw kiểm tra vị trí 'const' trong câu trả lời của bạn), và' const & 'có thể bị ràng buộc vào thời gian chờ ... đây là làm tôi thất vọng:/ –

1

Trong một "pass by reference" cuộc gọi, nếu loại lập luận không phù hợp với "tham số chính thức", sau đó trình biên dịch sẽ cố gắng chuyển đổi đối số thành đúng loại. Đối số sẽ được coi là 'tham số giá trị' nếu chuyển đổi thành công. Trình biên dịch tạo ra cảnh báo "Tạm thời được sử dụng cho ..." trong trường hợp này.

+0

Làm việc cho tôi. int được sử dụng trong tham số unsigned. –

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