2012-05-04 27 views
5

Nếu tôi sử dụng auto_ptr như một giá trị trả về của một hàm mà populates vectơ lớn, điều này làm cho các chức năng một hàm nguồn (nó sẽ tạo ra một auto_ptr nội bộ và vượt qua quyền sở hữu khi nó trả về một tổ chức phi const auto_ptr). Tuy nhiên, tôi không thể sử dụng hàm này với các thuật toán STL bởi vì, để truy cập dữ liệu, tôi cần phải bỏ đăng ký lại auto_ptr. Một ví dụ tốt, tôi đoán sẽ là một trường vectơ có kích thước N, với mỗi vectơ có 100 thành phần. Wether chức năng trả về mỗi vector thành phần 100 theo giá trị hoặc bởi ref là không giống nhau, nếu N là lớn.trở lại giá trị tối ưu hóa vs auto_ptr cho vectơ lớn

Ngoài ra, khi tôi cố gắng mã rất cơ bản này:

class t 
{ 
    public: 
     t() { std::cout << "ctor" << std::endl; } 
     ~t() { std::cout << "dtor" << std::endl; } 
}; 

t valueFun() 
{ 
    return t(); 
} 

std::auto_ptr<t> autoFun() 
{ 
    return std::auto_ptr(new t()); 
} 

cả autoFun và các cuộc gọi vui là kết quả với sản lượng

ctor Dtor

vì vậy tôi có thể không thực sự thấy biến tự động mà đang được tạo ra để được thông qua cho câu lệnh trả về. Điều này có nghĩa là Tối ưu hóa giá trị trả lại được đặt cho lệnh gọi valueFun không? Liệu valueFun tạo ra hai đối tượng tự động ở tất cả trong trường hợp này?

Làm cách nào để tối ưu hóa một tập hợp cấu trúc dữ liệu lớn với chức năng?

+0

Bạn có hỏi liệu RVO cũng sẽ hoạt động cho các vectơ lớn của bạn không? Nếu vậy, bạn có thể thử nghiệm nó với một ví dụ như trên không? – juanchopanza

+0

Khi tôi kiểm tra nó, nó có nghĩa là nó hoạt động cho tất cả các trình biên dịch/nền tảng? Làm thế nào để tôi biết RVO được bao gồm ở tất cả, tôi nên đọc các thông số kỹ thuật của trình biên dịch? Điều gì sẽ xảy ra nếu mã được biên dịch trên một cụm HPC với trình biên dịch khác và thư viện lớn? – tmaric

+0

Vâng, tôi thấy quan điểm của bạn. Đó là một trong những thứ mà trình biên dịch được phép, nhưng không bắt buộc phải làm, vì vậy bạn không bao giờ có thể chắc chắn. BTW bạn có hỗ trợ C++ 11 không? – juanchopanza

Trả lời

4

có rất nhiều tùy chọn cho điều này, và phân bổ động thể không phải là tốt nhất.


Trước khi chúng tôi thảo luận trong cuộc thảo luận này: đây có phải là nút cổ chai không?

Nếu bạn không cấu và đảm bảo đó là một nút cổ chai, sau đó thảo luận này có thể là hoàn toàn tắt ... Ghi hơn profiling debug xây dựng là khá nhiều vô ích.


Bây giờ, trong C++ 03 có một số tùy chọn, từ ngon miệng nhất đối với ít nhất một:

  • tin tưởng trình biên dịch: biến giấu tên sử dụng RVO ngay cả trong Debug xây dựng trong gcc, cho thí dụ.
  • sử dụng một tham số "out" (vượt qua bằng cách tham khảo)
  • phân bổ trên heap và trả về một con trỏ (thông minh hay không)
  • kiểm tra trình biên dịch ra

Cá nhân, tôi sẽ tin tưởng biên dịch của tôi về điều này trừ khi một hồ sơ chứng minh tôi sai.

Trong C++ 11, di chuyển ngữ nghĩa giúp chúng ta tự tin hơn, bởi vì bất cứ khi nào có câu lệnh return, nếu RVO không thể khởi động, thì hàm tạo (nếu có) có thể được sử dụng tự động; và di chuyển các nhà thầu trên vector là giá rẻ.

Vì vậy, nó trở thành:

  • tin tưởng trình biên dịch: hoặc RVO hoặc di chuyển ngữ nghĩa
  • phân bổ trên heap và trả về một unique_ptr

nhưng thực sự là điểm thứ hai nên được sử dụng chỉ cho vài lớp học mà ngữ nghĩa di chuyển không giúp được gì nhiều: chi phí của ngữ nghĩa di chuyển thường tỷ lệ thuận với sự trở lại của sizeof, ví dụ: std::array<T,10> có kích thước bằng 10*sizeof(T) do đó không có t rất tốt và có thể hưởng lợi từ phân bổ đống + unique_ptr.


Tangent: bạn đã tin cậy trình biên dịch của mình rồi. Bạn tin tưởng nó để cảnh báo bạn về lỗi, bạn tin tưởng nó để cảnh báo bạn về các cấu trúc nguy hiểm/có thể không chính xác, bạn tin tưởng nó để dịch mã của bạn thành cụm máy, bạn tin tưởng nó để áp dụng tối ưu hóa có ý nghĩa. Không tin tưởng một trình biên dịch để áp dụng RVO trong các trường hợp rõ ràng là không tin tưởng bác sĩ phẫu thuật tim của bạn với một hóa đơn $ 10: đó là ít nhất của những lo lắng của bạn. ;)

+1

Cảm ơn rất nhiều về sự tiếp xúc! :) – tmaric

1

Tôi khá chắc chắn rằng trình biên dịch sẽ thực hiện Tối ưu hóa giá trị trả lại cho valueFun. Các trường hợp chính nơi tối ưu hóa giá trị trả về không thể áp dụng bởi trình biên dịch là:

  • trở về thông số
  • trả về một đối tượng khác nhau dựa trên một điều kiện

Do đó auto_ptr là không cần thiết, và sẽ là thậm chí còn chậm hơn do phải sử dụng heap.

Nếu bạn vẫn còn lo lắng về chi phí di chuyển xung quanh một vectơ lớn, bạn có thể muốn xem xét sử dụng ngữ nghĩa di chuyển (std::vector aCopy(std::move(otherVector)) của C++ 11. Chúng gần như nhanh như RVO và có thể được sử dụng bất cứ nơi nào (nó cũng đảm bảo sẽ được sử dụng cho các giá trị trở lại khi RVO không có khả năng được sử dụng.)

tôi tin rằng trình biên dịch hiện đại nhất ngữ nghĩa hỗ trợ di chuyển (hoặc tham chiếu rvalue về mặt kỹ thuật) vào thời điểm này

+0

"khá chắc chắn" là những gì làm phiền tôi một chút. :) Từ quan điểm của tôi, nếu tôi chạy điều này trên 100 lõi và nếu nó sẽ phát triển theo thời gian, tôi cần phải chắc chắn 100% những gì mã đó làm. – tmaric