2010-10-30 18 views
11

सी ++ 03 §4.2 N ° 1 आए हैं हो सकता है:
एक lvalue या प्रकार के rvalue "NT की सरणी" या "की सरणी अज्ञात बाध्य टी "को प्रकार के एक रैल्यू में परिवर्तित किया जा सकता है" सूचक से टी। "परिणाम सरणी के पहले तत्व के लिए एक सूचक है।मुझे लगता है मैं सरणी प्रकार के rvalue का एक उदाहरण के साथ

क्या मेरे लिए एक लंबे समय के लिए इस बयान में भ्रमित किया गया है था कि मैं काफी समझ में नहीं आया कि क्या सरणी प्रकार का एक rvalue मतलब होगा। यही है, मैं एक अभिव्यक्ति के साथ नहीं आ सकता था जिसका प्रकार एक सरणी थी और नतीजा एक रावल था। मैंने this धागा पढ़ा, जो मूल रूप से एक ही प्रश्न पूछता है और स्वीकृत उत्तर "नहीं, सरणी प्रकार का कोई रावलू नहीं है"। मुझे लगता है कि मैं बस इसके लिए एक विरोधाभास हो सकता है।

सी ++ 03 §5.2.5 N ° 4: (अभिव्यक्ति E1.E2 के बारे में है)
E2 एक गैर स्थिर डेटा सदस्य है, और ई 1 के प्रकार के "CQ1 vq1 है एक्स ", और ई 2 का प्रकार" सीक्यू 2 वीक 2 टी "है, अभिव्यक्ति पहली अभिव्यक्ति द्वारा निर्दिष्ट ऑब्जेक्ट के नामित सदस्य को निर्दिष्ट करती है। यदि ई 1 एक लालसा है, तो E1.E2 एक अंतराल है।

मुझे लगता है कि अन्यथा यह (है एक संदर्भ, उस मामले §5.2.5 N°3 द्वारा कवर किया जाता E2 उपलब्ध नहीं) एक rvalue है और इसलिए ...

struct A 
{ 
    int a[4]; 
}; 
A f() 
{ 
    A a; 
    return a; 
} 
int main() 
{ 
    f().a; //I think this is an rvalue of array type... 
} 

मैं यहाँ दो विकल्प देखेंगे:
विकल्प 1: मैं सही हूँ, hurray, yay, cool। इस मामले में सवाल यह है: क्या अन्य उदाहरण हैं?
विकल्प 2: मैं गलत हूं, इस मामले में सवाल यह है: क्या यह मानक का दोष है?

मुझे 1 के बारे में पता नहीं है, लेकिन मुझे वास्तव में 2 के बारे में संदेह है क्योंकि जब वे फ़ंक्शन-टू-पॉइंटर रूपांतरणों के बारे में बात करते हैं तो वे फ़ंक्शन प्रकारों के केवल lvalues ​​का उल्लेख करते हैं (जाहिर है कि इस तरह की कोई रैल्यू नहीं है)। तो यह बहुत संभावना है कि उन्होंने सरणी प्रकारों के आबादी के बारे में सोचा था।

तो, मूल रूप से मेरा प्रश्न यह है कि क्या मैं सरणी प्रकार के रावल्यू के उदाहरण के साथ आया हूं, और यदि नहीं, तो कृपया एक वैध प्रदान करें, जिसे मैं दृढ़ता से मानता हूं कि वहां मौजूद है।

उत्तर

11

हां, आप सही हैं। अभिव्यक्ति सरणी प्रकार का एक रैल्यू है। यह एक दोष नहीं है - समिति इसके बारे में जानता है, और यह सी 8 9 में भी एक आम मुद्दा था, जो केवल सरणी प्रकारों के अंतराल के लिए पॉइंटर्स को रूपांतरण की अनुमति देता है। नतीजतन, आप f().a जैसे सरणी को इंडेक्स या डिफरेंस नहीं कर सके। सी 99 ने इसे ठीक किया, और सी ++ में इसके साथ कोई समस्या नहीं है।

ध्यान दें कि यह एक रावल्यू है या नहीं, अभिव्यक्ति किसी ऑब्जेक्ट को इंगित करती है या नहीं। सी ++ 03 ने गलती से यह कहने के लिए छोड़ा कि सरणी प्रकार की एक रैल्यू अभिव्यक्ति किसी ऑब्जेक्ट को दर्शाती है। यह सी ++ 0x by DR#450 में तय किया गया था।

(स्पष्ट रूप से प्रशंसा इस तरह का कोई rvalues ​​देखते हैं कि)

वास्तव में समारोह प्रकार के rvalues ​​हैं। ये क्लास सदस्य एक्सेस अभिव्यक्ति

struct A { void f(); }; 

/* A().f is an rvalue of type "void()" */ 
int main() { A().f(); } 
struct A { void f(); }; 

/* A().f is an rvalue of type "void()" */ 
int main() { A().f(); } 
+0

धन्यवाद! तो क्या आप जानते हैं कि यह रावलू सरणी का एकमात्र मामला है, जिसे बनाया जाता है। या ->। क्या अन्य उदाहरण हैं? –

+0

@ आर्मेन मैं एक और मामला नहीं सोच सकता (सी ++ 03 के लिए)। –

+1

@ आर्मेन नोट करें कि परिणामस्वरूप, आओउ कहता है कि 'ए()। ए' प्रकार' int [4] 'है, भले ही आपने सरणी को' const int a [4]; 'के रूप में घोषित किया हो। ऐसा इसलिए है क्योंकि मानक कहता है कि गैर-वर्ग प्रकारों के राजस्व कभी-कभी सीवी-योग्य नहीं होते हैं, और क्योंकि ईडीजी फ्रंटएंड एरे के सीवी-योग्यता और उनके तत्व प्रकारों को द्विपक्षीय रूप से समकक्ष के रूप में लेता है (मूल समस्या # 1059 देखें)। –

-3

ए एक रावल्यू है। इसके अंदर सरणी नहीं है। मामला है जिसमें आपको लगता है कि अस्थायी वस्तु पर एक विधि श्रृंखला की कल्पना - यह भीतर चर एक से अधिक विधि कॉल और वापसी के लिए रहते हैं, और वे संदर्भ अन्य कार्यों के लिए (श्रृंखला की अवधि के लिए वैध) पास कर सकते हैं। उन कार्यों को पहले से पता नहीं हो सकता है कि उन्हें एक रावल्यू पर बुलाया जाएगा।

मसौदे के नवीनतम संस्करण में, आप रावल/लवल्यू * पर कार्यों को अधिभारित कर सकते हैं। हालांकि, फिर भी, एक rvalue संदर्भ क्या एक rvalue में जाना जाता है की सामग्री को नहीं है, और मैं पूरी तरह से सुनिश्चित करें कि किसी भी संकलक वर्तमान में इस का समर्थन करता है नहीं कर रहा हूँ, और मुझे लगता है कि MSVC नहीं पता है।

दरअसल, decltype का उपयोग कर, आप आसानी से तय कर सकते हैं कि संकलक कि सरणी एक lvalue कहता है।

पर विचार करें:

template<typename A, typename B> auto sum(A&& a, B&& b) -> decltype(std::forward<A>(a) + std::forward<B>(b)) { 
    return std::forward<A>(a) + std::forward<B>(b); 
} 

है यही कारण है कि decltype के लिए था, और यह सबसे निश्चित रूप से lvalues ​​और rvalues ​​बीच अंतर। वैकल्पिक रूप से, इस पर विचार करें:

int main() 
{ 
    auto var = f().a; 
} 

Var एक int * है। यह एक तत्काल असफल है, क्योंकि एफ()। तुरंत मर जाता है। उस पर मेरी तत्काल राय के बारे में सुनिश्चित नहीं है, लेकिन यह निश्चित रूप से एक रावल्यू के लिए मान्य नहीं है।

+0

अस्वीकरण रावल और अंतराल के बीच अंतर नहीं करता है, जो गैर-स्थैतिक सदस्य फ़ंक्शंस के लिए होते हैं। और कृपया मानक से मेरा दूसरा उद्धरण एक बार फिर पढ़ें। –

+0

@ आर्मेन: अस्वीकरण का पूरा बिंदु अंतर करना है। सही आगे बढ़ने से भी काम करना शुरू हो सकता है? – Puppy

+2

@DeadMG decltype (expr) expr का प्रकार है। चाहे एक लापरवाही या रैवल्यू का एक्स्प्रेस है या नहीं, इसके प्रकार से कोई लेना देना नहीं है। –

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

  • कोई संबंधित समस्या नहीं^_^