मुझे लगता है कि नहीं, लेकिन मैं पुष्टि करना चाहता हूं। क्या इसका कोई उपयोग है const Foo&&
, जहां Foo
एक वर्ग प्रकार है?
मुझे लगता है कि नहीं, लेकिन मैं पुष्टि करना चाहता हूं। क्या इसका कोई उपयोग है const Foo&&
, जहां Foo
एक वर्ग प्रकार है?
जवाबों:
वे कभी-कभी उपयोगी होते हैं। C ++ 0x का मसौदा स्वयं उन्हें कुछ स्थानों पर उपयोग करता है, उदाहरण के लिए:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
उपर्युक्त दो अधिभार यह सुनिश्चित करते हैं कि अन्य ref(T&)
और cref(const T&)
फ़ंक्शंस प्रतिद्वंद्वियों के लिए बाध्य नहीं हैं (जो अन्यथा संभव होगा)।
अपडेट करें
मैंने अभी आधिकारिक मानक N3290 की जांच की है , जो दुर्भाग्य से सार्वजनिक रूप से उपलब्ध नहीं है, और इसमें 20.8 फ़ंक्शन ऑब्जेक्ट्स [function.objects] / P2 हैं:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
तब मैंने सबसे हालिया पोस्ट-सी ++ 11 ड्राफ्ट की जांच की, जो सार्वजनिक रूप से उपलब्ध है, N3485 , और 20.8 फ़ंक्शन ऑब्जेक्ट्स [function.objects] / P2 में यह अभी भी कहता है:
template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;
const T&&
का उपयोग किया जाता है?
const T&&
प्रपत्र के स्पष्ट टेम्पलेट आर्गन्स का उपयोग करके किसी को मूर्खतापूर्ण तरीके से रोकता है ref<const A&>(...)
। यह बहुत मजबूत तर्क नहीं है, लेकिन const T&&
अधिक लागत T&&
बहुत कम है।
पाने का शब्दार्थ कॉन्स्टेबल रैवल्यू रेफरेंस (और नहीं के लिए=delete
):
निम्नलिखित उपयोग का मामला IMHO हो सकता है, क्योंकि कास्ट के संदर्भ में संदर्भ के लिए एक अच्छा उपयोग मामला है , हालांकि भाषा ने इस दृष्टिकोण को नहीं लेने का फैसला किया ( मूल एसओ पोस्ट देखें )।
यह आमतौर पर उपयोग करने के लिए उचित होगा make_unique
औरmake_shared
, लेकिन दोनों unique_ptr
का shared_ptr
निर्माण कच्चे सूचक से किया जा सकता है। दोनों कंस्ट्रक्टर पॉइंटर को वैल्यू द्वारा प्राप्त करते हैं और इसे कॉपी करते हैं। दोनों अनुमति देते हैं (अर्थात के रूप में: को रोकने के लिए नहीं ) निर्माण में उन्हें करने के लिए पारित मूल सूचक का एक निरंतर उपयोग।
निम्नलिखित कोड डबल फ्री के साथ संकलित करता है और परिणाम देता है :
int* ptr = new int(9);
std::unique_ptr<int> p { ptr };
// we forgot that ptr is already being managed
delete ptr;
दोनों unique_ptr
और shared_ptr
उपरोक्त को रोक सकते हैं यदि उनके संबंधित निर्माता कच्चे संकेतक को एक तालमेल के रूप में प्राप्त करने की उम्मीद करेंगे , उदाहरण के लिए unique_ptr
:
unique_ptr(T* const&& p) : ptr{p} {}
जिस मामले में डबल फ्री है उपरोक्त कोड संकलित नहीं होगा, लेकिन निम्नलिखित होगा:
std::unique_ptr<int> p1 { std::move(ptr) }; // more verbose: user moves ownership
std::unique_ptr<int> p2 { new int(7) }; // ok, rvalue
ध्यान दें कि ptr
यह स्थानांतरित होने के बाद भी इस्तेमाल किया जा सकता है, इसलिए संभावित बग पूरी तरह से नहीं चला गया है। लेकिन अगर उपयोगकर्ता को std::move
इस तरह के बग को कॉल करना आवश्यक है , तो सामान्य नियम में आ जाएगा: एक संसाधन का उपयोग न करें जो ले जाया गया था।
एक पूछ सकता है: ठीक है, लेकिन क्यों T*
कास्ट&& p
?
कारण सरल है, unique_ptr
कास्ट पॉइंटर से निर्माण की अनुमति देने के लिए । याद रखें कि स्थिरांक rvalue संदर्भ बस की तुलना में अधिक सामान्य है rvalue संदर्भ के रूप में यह दोनों स्वीकार करता है const
औरnon-const
। तो हम निम्नलिखित की अनुमति दे सकते हैं:
int* const ptr = new int(9);
auto p = std::unique_ptr<int> { std::move(ptr) };
अगर हम सिर्फ रेवल्यू रेफ़रेंस (संकलन त्रुटि: उम्मीद नहीं कर सकते, तो रिवल्यूड को रेव्यू नहीं बाँध सकते ) जाएगा।
किसी भी तरह, यह इस तरह की बात करने के लिए बहुत देर हो चुकी है। लेकिन यह विचार कब्ज के संदर्भ में एक उचित उपयोग प्रस्तुत करता है ।
उन्हें अनुमति दी जाती है और यहां तक कि कार्यों के आधार पर रैंक की जाती है const
, लेकिन चूंकि आप द्वारा निर्दिष्ट कास्ट ऑब्जेक्ट से नहीं जा सकते हैं const Foo&&
, इसलिए वे उपयोगी नहीं हैं।
const T&, T&, const T&&, T&&
Std :: Ref के अलावा , मानक पुस्तकालय std :: as_const में const rvalue संदर्भ का भी उपयोग करता है में इसी उद्देश्य के लिए ।
template <class T>
void as_const(const T&&) = delete;
इसका उपयोग std :: वैकल्पिक में वापसी मान के रूप में भी किया जाता है : लिपटे हुए मूल्य को प्राप्त करते समय :
constexpr const T&& operator*() const&&;
constexpr const T&& value() const &&;
साथ ही std :: get में :
template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;
यह मुमकिन है कि लिपटे हुए मूल्य का उपयोग करते समय मूल्य श्रेणी के साथ-साथ आवरण की निरंतरता को बनाए रखने के लिए।
इससे फर्क पड़ता है कि लिपटे ऑब्जेक्ट पर कांस्टेबल रिफ़ल-क्वालिफाइड फ़ंक्शंस को बुलाया जा सकता है या नहीं। उस ने कहा, मुझे पता नहीं है कि कास्ट रिवल्यू रेफ योग्य कार्यों के लिए कोई उपयोग नहीं है।
मैं ऐसी स्थिति के बारे में नहीं सोच सकता जहाँ यह सीधे उपयोगी होगी, लेकिन इसका अप्रत्यक्ष रूप से उपयोग किया जा सकता है:
template<class T>
void f(T const &x) {
cout << "lvalue";
}
template<class T>
void f(T &&x) {
cout << "rvalue";
}
template<class T>
void g(T &x) {
f(T());
}
template<class T>
void h(T const &x) {
g(x);
}
T in g , T कास्ट है, इसलिए f का x एक T कॉन्स्टेबल है।
यह संभवतया f (जब वह ऑब्जेक्ट को स्थानांतरित करने या उसका उपयोग करने का प्रयास करता है) में एक गंभीर त्रुटि के परिणामस्वरूप होता है, लेकिन f एक प्रतिद्वंद्विता-रेफ ले सकता है , ताकि इसे रिवेल्यू को संशोधित किए बिना lvalues पर नहीं बुलाया जा सके (जैसा कि बहुत सरल है) ऊपर उदाहरण)।
const&&
यह बहुत महत्वपूर्ण है, हालांकि वह यह नहीं कहता कि क्यों: youtube.com/watch?v=JhgWFYfdIho#t=54m20s