2013-04-06 4 views
10

मेरे पास एक प्रकार है जो कॉपी करने योग्य है, लेकिन कॉपी करने के लिए महंगा हो सकता है। मैंने चालक कन्स्ट्रक्टर को कार्यान्वित किया है और असाइनमेंट ले जाया है। लेकिन मेरे पास प्रदर्शन समस्याएं हैं जहां लोग मूल्य से गुजरते समय चाल() को कॉल करना भूल जाते हैं।क्या एक प्रकार केवल स्थानांतरित होना चाहिए, सिर्फ इसलिए कि प्रतिलिपि महंगा हो सकती है?

क्या यह प्रतिलिपि बनाने वाले को हटाने के लिए अच्छा सी ++ 11 शैली है, और इसके बजाय दुर्लभ मामलों के लिए एक स्पष्ट प्रति() विधि प्रदान करते हैं जब एक प्रति वास्तव में वांछित होती है? यह अन्य भाषाओं में रूढ़िवादी है (रूबी, जावास्क्रिप्ट) लेकिन मुझे सी ++ मानक लाइब्रेरी में कुछ भी पता नहीं है जो पूरी तरह से प्रदर्शन के लिए प्रतिलिपि प्रतिबंधित करता है। उदाहरण के लिए, std :: vector <> कॉपी करने योग्य है, जबकि std :: unique_ptr <> और std :: thread अन्य कारणों से गैर प्रतिलिपि योग्य नहीं हैं।

+2

मुझे लगता है कि 'कॉपी' सदस्य फ़ंक्शन के साथ समस्या यह है कि यह सभी टेम्पलेट कोड को तोड़ता है जो असाइनमेंट ऑपरेटर का उपयोग करता है। – Pubby

उत्तर

11

क्या एक प्रकार केवल स्थानांतरित होना चाहिए, सिर्फ इसलिए कि प्रतिलिपि महंगा हो सकती है?

नहीं

T a; 
T a = b; 
: अर्थ विज्ञान अपने प्रकार के ऐसी है कि वह कॉपी करने धारणात्मक सार्थक उपलब्ध कॉपी करने बनाने के लिए सही तरीका है, तो है एक प्रति निर्माता लागू, और उपयोगकर्ता इसे लागू करने के लिए मानक वाक्य रचना को अपनाने के लिए एक मौका देने का है

T c = std::move(a); // I'm doing it right (if I no longer need object a); 
T d = b; // If I don't need b anymore, I'm doing it wrong. 

और तुम्हारा के कुछ कार्यों के लिए अगर (किसी भी कारण से) यह हमेशा होता है:

अगर लोगों वस्तुओं से स्थानांतरित करने के लिए नहीं भूल जाएगा वे अब का उपयोग नहीं करना चाहते हैं ... ठीक है, कि उनके बुरा है वांछनीय है कि कॉलर एक ऑब्जेक्ट प्रदान करता है जिससे इसे स्थानांतरित करना संभव है, फिर फ़ंक्शन को स्वीकार करें रावल्यू संदर्भ:

void foo(my_class&& obj); 

my_class a; 
foo(a); // ERROR! 
foo(std::move(a)); // OK 
+1

कुछ संदर्भों में, कॉपी निर्माण के माध्यम से कॉपी करने योग्य प्रकारों की प्रतिलिपि नहीं बनाई जानी चाहिए: इंटरफ़ेस कक्षाओं (या गैर-अंतिम कार्यान्वयन) के लिए 'आभासी टी * क्लोन() const = 0' प्रतिलिपि व्यक्त करता है, फिर भी एक प्रतिलिपि निर्माता के रूप में लागू नहीं किया जा सकता है। अब, 'value_ptr 'रैपर आपको कॉपी निर्माण की दुनिया में वापस कर सकते हैं, लेकिन' टी' क्लास स्वयं कॉपी करने योग्य है, फिर भी एक प्रतिलिपि नहीं है (कम से कम एक सार्वजनिक नहीं)। – Yakk

+1

@Yakk: मैं सहमत नहीं हूं। किसी भी मानक कंटेनर की प्रतिलिपि बनाने के लिए बहुत महंगा हो सकता है, फिर भी यह कॉपी करने योग्य है। व्यक्तिगत रूप से, मेरा मानना ​​है कि "प्रतिलिपि" के संचालन में भाषा द्वारा परिभाषित एक अर्थशास्त्र और भाषा द्वारा परिभाषित एक वाक्यविन्यास है। उन दो चीजों से मेल खाना चाहिए। –

+0

मुझे लगता है कि आप मेरे जवाब पर टिप्पणी करना चाहते थे, मेरी टिप्पणी नहीं। :) – Yakk

1

नहीं। यदि प्रकार कॉपी करने योग्य है तो प्रकार कॉपी करने योग्य है। इसका मतलब है कि इसकी प्रतिलिपि निर्माता उपलब्ध है और काम करता है। इसका मतलब यह नहीं है कि कुछ सदस्य फ़ंक्शन का नाम है जिसका नाम c, o, p और y अनुक्रम में दिखता है, जो "लगभग समान चीज़ों की तरह" होता है।

+0

तो, यदि वे कॉपी निर्माण को अक्षम करते हैं, तो प्रकार कॉपी करने योग्य नहीं है। यह डुप्लिकेट करने योग्य, क्लोनेबल, या कुछ अन्यथा समानार्थी शब्दकोष है - लेकिन स्पष्ट रूप से कॉपी करने योग्य नहीं है। यह एक समस्या कैसी है? – Yakk

+1

@Yakk: मैं आपके वर्गीकरण से सहमत हूं। कोई समस्या है? खैर, कौन जानता है? इस पर निर्भर करता है कि आप अपने प्रकार के लिए क्या चाहते हैं। लेकिन आप निश्चित रूप से इसे और अधिक प्रतिलिपि नहीं कहेंगे, और जहां तक ​​कोड के कई अन्य टुकड़े चिंतित हैं (जैसे कंटेनर), आपके प्रकार को कभी भी कॉपी नहीं किया जाएगा, क्योंकि आपने इसे ऐसा किया है। –

+0

ठीक है, मैं विश्लेषण से असहमत नहीं हूं। मैं अपने प्रकार को गैर-प्रतिलिपि बनाने का प्रस्ताव कर रहा हूं, इस तथ्य के बावजूद कि यह स्पष्ट रूप से एक मूल्य प्रकार है। –

4

यदि प्रति पर्याप्त रूप से महंगा है तो मैं वर्ग को हस्ताक्षर में गैर-प्रतिलिपि के रूप में मानूंगा। अर्थात् चीजें केवल तभी कॉपी की जा सकती हैं जब आप उन्हें बनना चाहते हैं, और एक महंगी प्रति "तय करने योग्य नहीं" तय करने का एक सभ्य कारण है।

कुछ कॉपी करने की क्षमता का मतलब यह नहीं है कि इसे कॉपी करने योग्य प्रकार में लागू किया जाना चाहिए। उस प्रकार के कार्यान्वयनकर्ता को यह तय करना पड़ता है कि क्या इसे अर्थात् प्रतिलिपि बनाना चाहिए।

मैं उस ऑपरेशन को नहीं बुलाऊंगा जिसने एक महंगी प्रति "प्रतिलिपि" बनाई, बल्कि "क्लोन" या "डुप्लिकेट" बनाई।

एक तरह से आप यह कर सकते हैं के लिए:

#include <utility> 

template<typename T> 
struct DoCopy { 
    T const& t; 
    DoCopy(T const& t_):t(t_) {} 
}; 
template<typename T> 
DoCopy<T> do_copy(T const& t) { 
    return t; 
} 
struct Foo { 
    struct ExpensiveToCopy { 
    int _[100000000]; 
    }; 
    ExpensiveToCopy* data; 
    Foo():data(new ExpensiveToCopy()) {} 
    ~Foo(){ delete data; } 
    Foo(Foo&& o):data(o.data) { o.data = nullptr; } 
    Foo& operator=(Foo&& o) { data=o.data; o.data=nullptr; return *this; } 
    Foo& operator=(DoCopy<Foo> o) { 
    delete data; 
    if (o.t.data) { 
     data=new ExpensiveToCopy(*o.t.data); 
    } else { 
     data=new ExpensiveToCopy(); 
    } 
    return *this; 
    } 
    Foo(DoCopy<Foo> cp):data(cp.t.data?new ExpensiveToCopy(*cp.t.data):new ExpensiveToCopy()) {}; 
}; 
int main() { 
    Foo one; 
    // Foo two = one; // illegal 
    Foo three = std::move(one); // legal 
    Foo four; 
    Foo five = do_copy(three); 
    four = std::move(three); 
    five = do_copy(four); 
} 

यह ऐसी तकनीकों के समान कमियां, अर्थात् के साथ, कुछ हद तक तरीकों से आप std::move rvalue संदर्भ के अस्तित्व से पहले अर्थ विज्ञान की तरह लिखा जा सकता था के समान है कि भाषा को स्वयं ही पता नहीं है कि आप किस शेंगेनियन हैं।

यह लाभ यह है कि इसके बाद के संस्करण do_copy की वाक्य रचना std::move की वाक्य रचना के समान है है, और यह आप बिना पारंपरिक एक्सप्रेशन का उपयोग करने Foo की तुच्छ उदाहरण बना करने के लिए फिर एक और चर आदि की एक प्रति का निर्माण की अनुमति देता है

यदि ऐसी स्थितियां जहां हम इसे कॉपी करने योग्य के रूप में पेश करना चाहते हैं, तो आम हैं (यदि टाला जाना है), तो मैं कक्षा के चारों ओर एक प्रति-रैपर लिखूंगा जो duplicate विधि के बारे में जानता है।

+1

मैं अपनी लाइब्रेरी का उपयोगकर्ता न्यायाधीश बनूंगा। –

+0

मुझे यह समाधान पसंद है। मैंने कॉपी करने योग्य पदानुक्रमों के लिए कुछ ऐसा किया है, और चाल-जैसी वाक्यविन्यास एक अच्छा स्पर्श है। –

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

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