2010-01-20 35 views
8

http://www.cplusplus.com/reference/algorithm/for_each/
Chức năng đơn nhất lấy phần tử trong phạm vi làm đối số. Điều này có thể là con trỏ đến hàm hoặc đối tượng có quá tải lớp học toán tử(). Giá trị trả lại của nó, nếu có, bị bỏ qua.Tại sao for_each không thể sửa đổi đối số functor của nó?

Theo bài viết này, tôi mong rằng for_each thực sự sửa đổi đối tượng được đưa ra làm đối số thứ ba, nhưng có vẻ như for_each hoạt động trên đối tượng tạm thời và thậm chí không sửa đổi đối tượng được cung cấp.

Vì vậy, tại sao nó được triển khai theo cách đó? Nó có vẻ ít hữu ích hơn nhiều. Hoặc tôi đã hiểu sai một cái gì đó và mã của tôi dưới đây có chứa lỗi?

#include <iostream> 
#include <vector> 
#include <algorithm> 

template <class T> struct Multiplicator{ 
    T mresult; 
    public: 
    const T& result() const{return mresult;} 
    Multiplicator(T init_result = 1){ 
     mresult = init_result; 
    } 
    void operator()(T element){ 
     mresult *= element; 
     std::cout << element << " "; // debug print 
    } 
}; 

int main() 
{ 
    std::vector<double> vec; 
    vec.push_back(1); 
    vec.push_back(2); 
    vec.push_back(3); 
    Multiplicator<double> multiply; 
    std::for_each(vec.begin(),vec.end(),multiply); 
    std::cout << "\nResult: " << multiply.result() << std::endl; 
    return 0; 
} 

sản lượng dự kiến:

1 2 3 Result: 6 

Nhưng đã sau đầu ra:

1 2 3 Result: 1 
+0

Cách thay đổi tiêu đề câu hỏi của bạn? Có thể giúp người khác dễ dàng tìm thấy. – BeeBand

Trả lời

15

Đối tượng chức năng được thực hiện bởi giá trị. for_each trả về đối tượng hàm, vì vậy nếu bạn thay đổi thành:

multiply = std::for_each(vec.begin(),vec.end(),multiply); 

bạn sẽ nhận được kết quả mong đợi.

+1

Nói chung cho các functors, và vì chúng được coi là nhẹ và có thể sao chép được, tôi lừa và sử dụng một thuộc tính tham chiếu đến một biến được truyền vào hàm tạo. Vì vậy, bất kỳ bản sao nào đều tương đương nhau và đề cập đến cùng một mục. Tất nhiên, nó làm cho khởi tạo một chút vụng về (khai báo biến, chuyển nó tới functor, đọc từ biến), nhưng nó hoạt động tốt và không yêu cầu bất kỳ sự thực thi cụ thể nào (như không loại bỏ functor đã sửa đổi). –

+0

Lemme cung cấp cho bạn huy hiệu STL vàng đầu tiên –

+0

@Johannes: Cảm ơn bạn, nhưng tôi phải trả lời 36 câu hỏi khác được gắn thẻ [stl] đầu tiên :-) (yêu cầu hiện có ít nhất 1.000 phiếu bầu và ít nhất 200 câu trả lời; họ đã thay đổi nó một năm trước và tôi đã mất huy hiệu vàng [c] trong một vài tháng.) –

10

Trong khi James là đúng, sử dụng std::accumulate với std::multiplies sẽ chính xác hơn, có lẽ:

#include <iostream> 
#include <functional> 
#include <numeric> 
#include <vector> 

int main(void) 
{ 
    std::vector<double> vec; 
    vec.push_back(1); 
    vec.push_back(2); 
    vec.push_back(3); 

    double result = std::accumulate(vec.begin(), vec.end(), 
            1.0, std::multiplies<double>()); 

    std::cout << "\nResult: " << result << std::endl; 

} 

Với phiên bản for_each của bạn, bạn không thực sự cần phải sao chép các functor một lần nữa, thay vì:

double result = std::for_each(vec.begin(), vec.end(), multiply).result(); 

Hoặc C++ 0x, cho vui:

double result = 1; 
std::for_each(vec.begin(), vec.end(), [&](double pX){ result *= pX; }); 
+0

Đây là gì, "đề xuất công cụ phù hợp cho ngày làm việc?" :-) +1 –

+0

Cảm ơn mẹo. – smerlin

+0

@James: 8) Thật không may, chất lượng câu trả lời của tôi giảm theo cấp số nhân khi ngày tiếp tục. : p – GManNickG

0

Ngữ nghĩa của For_each không phù hợp với những gì bạn đang cố gắng làm. tích lũy thực hiện chính xác những gì bạn đang cố gắng, sử dụng thay vào đó.

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