2016-03-21 24 views
5

ऐसा लगता है कि यह पहले से ही सबसे अधिक प्रचलित प्रश्न है।std :: move vs std :: आगे

Whats the difference between std::move and std::forward

लेकिन हर सवाल का जवाब अलग है और लागू होता है और थोड़ा अलग बातें कहते हैं। तो मैं उलझन में हूँ।

मेरे पास निम्न स्थिति है। कंटेनर
कॉपी मद में

  • कॉपी आइटम सी ++ 03 तो मैं बहुत अच्छी तरह से समझते हैं कि है।
  • कंटेनर
    कंटेनर में निर्माण मद में मेरा मानना ​​है कि
  • निर्माण आइटम सही रूप से सही अग्रेषण का उपयोग करता emplaceBackInternal() में टी के निर्माता के लिए दो कार्य के माध्यम से तर्क अग्रेषित करने के लिए (कृपया अन्यथा कहना है कि अगर मैं गलत हूँ)।
  • आइटम को कंटेनर में ले जाएं
    मेरी समस्या कंटेनर में किसी आइटम को स्थानांतरित करने की समझ में प्रतीत होती है।

कोड:

template<typename T> 
class Container 
{ 
    std::size_t length; 
    T*   buffer; 

public: 
    void push_back(T const& value) 
    { 
     resizeIfRequired(); 
     pushBackInternal(value); 
    } 
    template<typename... Args> 
    void emplace_back(Args&&... args) 
    { 
     resizeIfRequired(); 
     emplaceBackInternal(std::forward<T>(arg)...); 
    } 
    void push_back(T&& value) 
    { 
     resizeIfRequired(); 
     // Is this forward correct or should it be move 
     moveBackInternal(std::forward<T>(value)); 
    } 
private: 
    void pushBackInternal(T const& value) 
    { 
     // Copy construct object into buffer; 
     new (buffer + length) T(value); 
     ++length; 
    } 
    template<typename... Args) 
    void emplaceBackInternal(Args&&... args) 
    { 
     // Construct object into buffer using arguments; 
     new (buffer + length) T(std::forward<T>(args)...); 
     ++length; 
    } 
    void moveBackInternal(T&& value) 
    { 
     // Move construct object into buffer; 
     // Is this forward correct or should it be move 
     new (buffer + length) T(std::forward<T>(value)); 
     ++length; 
    } 
}; 

मैं सब यहाँ तीन जैसा कि पहले उल्लेख जवाब में प्रदान की जाती जवाब के साथ तीन कार्यों की तुलना करने में शामिल हैं। मुख्य कारण यह है कि move और construct ऐसा लगता है कि ऐसा लगता है कि वे समान होना चाहिए। एक टेम्प्लेटेड समारोह पैरामीटर

कास्ट करने के लिए इस परिभाषा मैं के रूप में std::movepush_back(T&& value) अंदर और moveBackInternal(T&& value) का उपयोग करना चाहिए द्वारा:

Answer @Potatoswatter Score 67

std :: आगे एक भी उपयोग के मामले है मान फ़ंक्शन के लिए टेम्पलेट पैरामीटर नहीं है।

Answer @Howard Hinnant Score 38

तो Y एक lvalue संदर्भ है, परिणाम एक lvalue अभिव्यक्ति हो जाएगा। यदि वाई एक लवल्यू संदर्भ नहीं है, तो परिणाम (सटीक होने के लिए xvalue) अभिव्यक्ति होगा।

इस परिभाषा के अनुसार लगता है कि मैं या तो std::move या std::forward का उपयोग कर सकता हूं।

Answer @Bo Persson Score 11

std :: आगे एक पैरामीटर वास्तव में जिस तरह से यह एक समारोह को पारित किया गया था अग्रेषित करने के लिए प्रयोग किया जाता है।

कहना है कि std::forward स्वीकार्य है (हालांकि अगर मैं जवाब में कड़ी का अनुसरण सभी उदाहरणों टेम्प्लेट कार्यों का उपयोग) लगता है।

+0

एर ... आपका प्रश्न क्या है जिसका उत्तर दिए गए उत्तरों द्वारा उत्तर नहीं दिया गया था? – Barry

+0

एर ... कौन सा जवाब सही है! प्रत्येक एक अलग परिणाम निर्दिष्ट करता है। –

+0

वे सभी सही हैं। दो बस कहना है कि 'std :: forward' का इरादा संदर्भ अग्रेषण के लिए है और तीसरा अतिरिक्त समय बताता है कि 'std :: forward' क्या है। – Barry

उत्तर

5

इस मामले में:

void push_back(T&& value) 
{ 
    resizeIfRequired(); 
    moveBackInternal(std::forward<T>(value)); // (1)    
    moveBackInternal(std::move(value));  // (2) 

} 

std::forward<T>(value) और std::move(value) इस परिदृश्य में समान कर रहे हैं (यह (1) और (2) के बीच कोई फर्क नहीं पड़ता ... इसलिए (2) उपयोग करें)।

move xvalue के लिए बिना शर्त कास्ट है। वह रेखा आपको T&& प्रकार की अभिव्यक्ति देता है जो हमेशा एक रावलू है।

forward एक सशर्त कास्ट है। यदि T एक lvalue संदर्भ प्रकार है, तो यह एक lvalue पैदा करता है। अन्यथा (यदि यह या तो संदर्भ प्रकार या एक रावल्यू संदर्भ प्रकार नहीं है), यह एक रैल्यू पैदा करता है। हमारे मामले में, T एक संदर्भ प्रकार नहीं है - इसलिए हमें एक रावल्यू मिलता है।

किसी भी तरह से, हम एक ही बिंदु पर समाप्त होते हैं - हम moveBackInternal को value के साथ एक रावल्यू के रूप में कहते हैं। बस move() वहां पहुंचने का एक आसान तरीका है। forward<T> काम करता है, लेकिन यह अनावश्यक है।

+0

इसकी तरह इस तरह की इच्छा है कि मैं आपके साथ एक कार्यालय में था (या एक पोस्ट के लेखक) और बेहतर तकनीक के रूप में एक व्हाइटबोर्ड के साथ एक स्पष्ट चर्चा हो सकती है। - अगर मैं धारणा करता हूं कि 'std :: move' और' std :: forward' दोनों द्वारा किए गए सभी कार्यों पर समय कार्य संकलित किया गया है। फिर समाधान (1) बेहतर नहीं होगा क्योंकि यह कोड 'emplace_back() 'के समान दिखता है। मुझे दो अलग-अलग तकनीकों की आवश्यकता क्यों है जब मैं एक ऐसी तकनीक कर सकूं जो सभी परिस्थितियों में काम करे? कोड को बनाए रखने के लिए कम अंतर का मतलब आसान है? –

+0

@ लोकी एस्टरी मुख्य रूप से राय आधारित है। जब हम बिना शर्त चल रहे हैं तो मुझे 'move()' का उपयोग करने के लिए और अधिक सरल लगता है। 'Push_back()' कोड केवल कभी चलता है, तो अधिक जटिल कलाकार का उपयोग क्यों करें? आखिरकार, मुझे लगता है कि कुछ मूलभूत रूप से ... बंद है ... अग्रेषण संदर्भों के साथ। मुझे नहीं पता कि यह कैसे बेहतर किया जा सकता है - और बेहतर या बदतर के लिए, यह हमें मिला है। – Barry

+0

सभी इनपुट के लिए धन्यवाद। ईमानदार होने के लिए मैं अभी भी अपनी राय बनाने की कोशिश कर रहा हूं और सिर्फ शैतानों को यहां खेलने की कोशिश कर रहा हूं। :-) –

संबंधित मुद्दे