हो सकता है कि एलेक्स Stepanov कार्यात्मक प्रोग्रामिंग प्रतिमान था, लेकिन आपको लगता है कि std::accumulate
और std::for_each
दोनों, मूल्य से चारों ओर उनके ऑपरेंड (समारोह और संचित मूल्य) पारित नहीं बल्कि संदर्भ द्वारा की तुलना में मिल जाएगा। इस प्रकार:
class MyFunctor
{
Y val;
public:
MyFunctor() : val() {}
void operator()(X const& x)
{
// do something to modify val based on x
}
Y getValue() const { return val; }
};
अब अगर आप का प्रयास करें:
MyFunctor f;
for_each(coll.begin(), coll.end(), f);
Y y = f.getValue();
यह काम नहीं करेगा गया है क्योंकि for_each
f
की प्रतियां के साथ काम कर दिया। बेशक आप आंतरिक रूप से shared_ptr<Y>
का उदाहरण प्राप्त कर सकते हैं जो एक ही उदाहरण को इंगित करेगा। आप MyFunctor के अंदर वैल्यू भी एक संदर्भ बना सकते हैं, इसे लूप के बाहर बना सकते हैं और इसे MyFunctor में पास कर सकते हैं।
हालांकि भाषा आप की सुविधा देता है बस करो:
Y y = for_each(coll.begin(), coll.end(), MyFunctor()).getValue();
अच्छा और सुविधाजनक है, सभी एक पंक्ति में।
साथ std::accumulate
इस तरह से किया जाना होता भी ऐसा ही करने के लिए:
class MyFunctor2
{
public:
Y operator()(Y y, X const& x) const
{
// create a new Y based on the old one and x
...
}
};
Y y = std::accumulate(coll.begin(), coll.end(), Y(), MyFunctor2());
आप (या सी ++ 11 एक लैम्ब्डा में) एक समारोह का उपयोग एक functor के बजाय सकता है। ध्यान दें कि यहां मज़ेदार के पास कोई राज्य नहीं है, और आप अपने आरंभिक ऑब्जेक्ट को पैरामीटर के रूप में पास करते हैं, जो अस्थायी हो सकता है।
अब हम जानते हैं कि वाई कॉपी करने योग्य है। std::accumulate
वाई पर by value
का उपयोग करता है, न कि जगह में संशोधित। संयोग से जब यथा-स्थान वास्तव में, संशोधित करने, और अधिक कुशल है वहाँ एक नया एल्गोरिथ्म लिखे एक समाधान नहीं है (उदाहरण के लिए accumulate2 + = या संदर्भ संशोधन का उपयोग करता है) के एक समारोह हस्ताक्षर का उपयोग करके:
Y * func(Y* py, X const &); // function modifies *py in-place then returns py
तो
बुला:
Y y;
std::accumulate(coll.begin(), coll.end(), &y, func);
हम वापसी मान & y हो जाएगा "पता"। यदि हम वाई के किसी सदस्य को एक स्थान पर एक्सेस करना चाहते हैं तो हम इसका उपयोग कर सकते हैं उदा।
Y y;
Z z = std::accumulate(coll.begin(), coll.end(), &y, func)->getZ();
संयोग से, accumulate
में for_each
में कॉपी और नकल करने के लिए एक महत्वपूर्ण अंतर यह जटिलता/प्रतियां यह कर देगा की संख्या है। for_each
के साथ आपके मज़ेदार से बने 2 प्रतियां होंगी: एक फ़ंक्शन में पैरामीटर और रिटर्न में एक के रूप में। मैं "सबसे अधिक" कहता हूं क्योंकि रिटर्न वैल्यू ऑप्टिमाइज़ेशन इन प्रतियों में से दूसरी को कम कर सकता है। accumulate
के साथ यह संग्रह में हर तत्व के साथ प्रतिलिपि बनाता है, i.e O(N)
निरंतर समय के बजाय। इसलिए यदि प्रतिलिपि महंगी महंगी है, तो मज़ेदार में दोहरी प्रति बड़ी संग्रहों पर थोड़ी-थोड़ी बार फिर से खर्च करने का एक बड़ा खर्च नहीं होगा, जबकि जमा करने के लिए यह होगा (और सुझाव पॉइंटर हैक होगा)।
संभोग, मैंने इस बारे में क्यों नहीं सोचा? Thx :) – larsmoa
मुझे यहां एक समय पर बताया गया था (चार्ल्स बेली द्वारा, मुझे लगता है), कि इस व्यवहार की गारंटी नहीं है। मैंने उसे विश्वास नहीं किया; मैंने मानक को सोचा, जबकि अस्पष्ट, ज्यादातर उस संदर्भ में समझ में आया। (हम एक समारोह क्यों प्राप्त करेंगे?) लेकिन सिर्फ एक चेतावनी, शायद यह सिर्फ "मानक" कंपाइलर व्यवहार है और मानक व्यवहार नहीं है। – GManNickG
@GMan: फ़ंक्शन को वापस करने के लिए मानक (§25.1.1/2) आवश्यक है। –