क्या C ++ कोड C ++ 03 और C ++ 11 दोनों में मान्य हो सकता है लेकिन अलग-अलग काम करते हैं?


298

क्या C ++ कोड के लिए C ++ 03 मानक और C ++ 11 मानक दोनों के अनुरूप होना संभव है , लेकिन अलग-अलग चीजें करना किस मानक के तहत संकलित किया जा रहा है?


26
मुझे पूरा यकीन autoहै कि इस तरह की स्थिति में परिणाम हो सकता है
OMGtechy

8
हाँ। एक उदाहरण है >>जब एक टेम्पलेट में उपयोग किया जाता है। आप एक ऐसी स्थिति के साथ आ सकते हैं जहां यह दोनों मानकों के लिए संकलन कर सकता है। एक और जिस पर मुझे यकीन है कि इनिशियलाइज़ेशन में बदलाव खोजना आसान होगा।
क्रिस

5
यहाँ >> स्थिति पर एक अच्छा लेख है: gustedt.wordpress.com/2013/12/15/…
क्रिस

6
@OMGtechy: मुझे नहीं लगता कि auto यह कारण हो सकता है। पुराने अर्थ के साथ, एक autoघोषणा के लिए एक प्रकार का नाम आवश्यक है; नए अर्थ के साथ, एक प्रकार के नाम की अनुमति नहीं है।
कीथ थॉम्पसन

2
यह ओपन-एंडेड कैसे है? आपने स्वयं एक अन्य प्रश्न के माध्यम से बताया कि इस प्रश्न का उत्तर "हाँ, यहाँ एक उदाहरण है"। प्रश्न का बहुत ही निश्चित उत्तर है, जैसा कि आपने स्वयं बताया है।
जलेफ

जवाबों:


283

जवाब एक निश्चित हाँ है। प्लस साइड पर है:

  • कोड जो पहले अस्पष्ट रूप से कॉपी किए गए ऑब्जेक्ट अब संभवत: उन्हें स्थानांतरित कर देगा।

नकारात्मक पक्ष पर, कई उदाहरण मानक के परिशिष्ट सी में सूचीबद्ध हैं। भले ही सकारात्मक से कई अधिक नकारात्मक हैं, उनमें से प्रत्येक के होने की संभावना बहुत कम है।

स्ट्रिंग शाब्दिक

#define u8 "abc"
const char* s = u8"def"; // Previously "abcdef", now "def"

तथा

#define _x "there"
"hello "_x // Previously "hello there", now a user defined string literal

0 के रूपांतरण टाइप करें

C ++ 11 में, केवल शाब्दिक पूर्णांक अशक्त सूचक स्थिरांक हैं:

void f(void *); // #1
void f(...); // #2
template<int N> void g() {
    f(0*N); // Calls #2; used to call #1
}

पूर्णांक विभाजन और मोडुलो के बाद गोल परिणाम

C ++ 03 में कंपाइलर को 0 पर या नकारात्मक अनंत की ओर गोल करने की अनुमति दी गई थी। C ++ 11 में 0 की ओर गोल होना अनिवार्य है

int i = (-1) / 2; // Might have been -1 in C++03, is now ensured to be 0

नेस्टेड टेम्पलेट बंद ब्रेसिज़ के बीच व्हाट्सएप >>>>>

एक विशेषज्ञता या तात्कालिकता के अंदर >>इसके बजाय C ++ 03 में एक सही बदलाव के रूप में व्याख्या की जा सकती है। हालांकि मौजूदा कोड को तोड़ने की अधिक संभावना है: ( http://gustedt.wordpress.com/2013/12/15/a-disimprovement-observed-from-the-outside-right-angle-brackets/ से )

template< unsigned len > unsigned int fun(unsigned int x);
typedef unsigned int (*fun_t)(unsigned int);
template< fun_t f > unsigned int fon(unsigned int x);

void total(void) {
    // fon<fun<9> >(1) >> 2 in both standards
    unsigned int A = fon< fun< 9 > >(1) >>(2);
    // fon<fun<4> >(2) in C++03
    // Compile time error in C++11
    unsigned int B = fon< fun< 9 >>(1) > >(2);
}

ऑपरेटर newअब अन्य अपवादों को छोड़ सकता हैstd::bad_alloc

struct foo { void *operator new(size_t x){ throw std::exception(); } }
try {
    foo *f = new foo();
} catch (std::bad_alloc &) {
    // c++03 code
} catch (std::exception &) {
    // c++11 code
}

उपयोगकर्ता-घोषित विध्वंसक का एक अंतर्निहित अपवाद विनिर्देश उदाहरण है कि C ++ 11 में कौन से ब्रेकिंग परिवर्तन पेश किए गए हैं?

struct A {
    ~A() { throw "foo"; } // Calls std::terminate in C++11
};
//...
try { 
    A a; 
} catch(...) { 
    // C++03 will catch the exception
} 

size() कंटेनरों को अब O (1) में चलाना आवश्यक है

std::list<double> list;
// ...
size_t s = list.size(); // Might be an O(n) operation in C++03

std::ios_base::failurestd::exceptionअब से सीधे नहीं मिलता है

जबकि प्रत्यक्ष आधार वर्ग नया है, std::runtime_errorनहीं है। इस प्रकार:

try {
    std::cin >> variable; // exceptions enabled, and error here
} catch(std::runtime_error &) {
    std::cerr << "C++11\n";
} catch(std::ios_base::failure &) {
    std::cerr << "Pre-C++11\n";
}

11
अच्छा लगा, १। एक और एक एक उपयोगकर्ता नाशक ने घोषणा की कि अब परोक्ष है noexecpt(true)तो throwएक नाशक अब फोन करेगा में std::terminate। लेकिन मुझे उम्मीद है कि जिसने भी ऐसा कोड लिखा है वह इस बारे में खुश होगा!
टाइप 1232

4
लेकिन std :: system_error स्वयं (परोक्ष रूप से) std :: अपवाद से व्युत्पन्न है, इसलिए catch (std::exception &)अभी भी पकड़ता है std::ios_base::failure
user2665887

@ user2665887 आप सही हैं। यह अभी भी एक कार्यक्रम के व्यवहार को प्रभावित कर सकता है, लेकिन मैं अभी एक न्यूनतम उदाहरण के बारे में नहीं सोच सकता।
उदाहरण

4
मैं सुपर भ्रमित हूं, जैसा कि आप कहते हैं कि operator newयह सटीक है (यह अब फेंक सकता है std::bad_array_new_length), लेकिन आपका उदाहरण यह बिल्कुल नहीं दिखाता है। आपके द्वारा दिखाया गया कोड C ++ 03 और C ++ 11 AFAIK में समान है।
मूइंग डक

2
सूची का दूसरा पहलू :: आकार O (1) है कि ब्याह अब O (n) है
टोनी डेलरो

55

मैं आपको इस लेख और अनुवर्ती के लिए इंगित करता हूं , जिसका एक अच्छा उदाहरण है कि >>दोनों में संकलित करते हुए C ++ 03 से C ++ 11 तक अर्थ कैसे बदल सकता है।

bool const one = true;
int const two = 2;
int const three = 3;

template<int> struct fun {
    typedef int two;
};

template<class T> struct fon {
    static int const three = ::three;
    static bool const one = ::one;
};

int main(void) {
    fon< fun< 1 >>::three >::two >::one; // valid for both  
}

मुख्य भाग में लाइन है main, जो एक अभिव्यक्ति है।

C ++ 03 में:

1 >> ::three = 0
=> fon< fun< 0 >::two >::one;

fun< 0 >::two = int
=> fon< int >::one

fon< int >::one = true
=> true

C ++ 11 में

fun< 1 > is a type argument to fon
fon< fun<1> >::three = 3
=> 3 > ::two > ::one

::two is 2 and ::one is 1
=> 3 > 2 > 1
=> (3 > 2) > 1
=> true > 1
=> 1 > 1
=> false

एक ही अभिव्यक्ति के लिए बधाई, दो अलग-अलग परिणाम। दी गई, C ++ 03 एक चेतावनी के रूप में आया था जब मैंने इसका परीक्षण किया था।


यह अजीब है कि इसे C ++ 03 संस्करण के typenameलिए आवश्यकता नहीं है::two
zahir

3
एक अच्छा, यह करने के लिए trueया falseविभिन्न मानकों के लिए मूल्यांकन करने के लिए नीचे फोड़ा हो रही है । शायद हम इसे एक सुविधा परीक्षण के रूप में उपयोग कर सकते हैं </ joke>
cmaster - reicaate monica

@ ज़हीर, यह एक प्रकार नहीं है, सिर्फ एक मूल्य है।
क्रिस

अच्छी तरह से, उचित cmdline विकल्प इस बारे में चेतावनी देते हैं ( warning: comparisons like ‘X<=Y<=Z’ do not have their mathematical meaning [-Wparentheses]), लेकिन फिर भी एक अच्छा उदाहरण है कि कैसे अस्पष्ट ::ऑपरेटर अर्थ बदल जाता है (या तो वैश्विक गुंजाइश का उल्लेख करता है या इसके पहले सीधे खड़े होने वाले को डीफ्रेंसिंग करता है)
उदाहरण

@example, आश्चर्यजनक रूप से, GCC उस चेतावनी को देती है, लेकिन क्लैंग ऐसा नहीं करती है।
क्रिस

39

हां, कई परिवर्तन हैं जो समान कोड के कारण C ++ 03 और C ++ 11 के बीच भिन्न व्यवहार का परिणाम देंगे। अनुक्रमण नियम अंतर कुछ दिलचस्प बदलावों के लिए करते हैं, जिनमें कुछ पहले से अपरिभाषित व्यवहार अच्छी तरह से परिभाषित होते हैं।

1. एक आरंभिक सूची के भीतर एक ही चर के कई म्यूटेशन

एक बहुत ही दिलचस्प कोने का मामला एक प्रारंभिक चर के भीतर एक ही चर के कई परिवर्तन होगा, उदाहरण के लिए:

int main()
{
    int count = 0 ;
    int arrInt[2] = { count++, count++ } ;

    return 0 ;
}

C ++ 03 और C ++ 11 दोनों में यह अच्छी तरह से परिभाषित है लेकिन C ++ 03 में मूल्यांकन का क्रम अनिर्दिष्ट है लेकिन C ++ 11 में उनका मूल्यांकन उस क्रम में किया जाता है जिसमें वे दिखाई देते हैं । इसलिए यदि हम clangC ++ 03 मोड में इसका उपयोग करते हैं, तो यह निम्नलिखित चेतावनी प्रदान करता है ( इसे लाइव देखें ):

warning: multiple unsequenced modifications to 'count' [-Wunsequenced]

    int arrInt[2] = { count++, count++ } ;

                           ^        ~~

लेकिन C ++ 11 में एक चेतावनी प्रदान नहीं करता है ( इसे लाइव देखें )।

2. नए अनुक्रमण नियम I = ++ i + 1 बनाते हैं; C ++ 11 में अच्छी तरह से परिभाषित

C ++ 03 के बाद अपनाए गए नए अनुक्रमण नियम का अर्थ है:

int i = 0 ;
i = ++ i + 1;

C ++ 11 में अब अपरिभाषित व्यवहार नहीं है, यह दोष रिपोर्ट 637 में शामिल है । अनुक्रमण नियम और उदाहरण असहमत

3. नए अनुक्रमण नियम भी ++++ i बनाते हैं; C ++ 11 में अच्छी तरह से परिभाषित

C ++ 03 के बाद अपनाए गए नए अनुक्रमण नियम का अर्थ है:

int i = 0 ;
++++i ;

C ++ 11 में अब अपरिभाषित व्यवहार नहीं है।

4. थोड़ा और अधिक संवेदनशील वामपंथी बदलाव पर हस्ताक्षर किए

C ++ 11 के बाद के ड्राफ्ट में वे शामिल हैं N3485जो मैं नीचे दिए गए लिंक को एक बिट बिट को साइन बिट में शिफ्ट करने के अपरिभाषित व्यवहार को तय करता हूं । यह भी दोष रिपोर्ट 1457 में शामिल है । हॉवर्ड हिनांत ने थ्रेड में इस बदलाव के महत्व पर टिप्पणी की है कि क्या वाम-स्थानांतरण (<<) C ++ 11 में एक नकारात्मक पूर्णांक अपरिभाषित व्यवहार है?

5. कब्ज कार्यों को C ++ 11 में संकलित समय निरंतर अभिव्यक्तियों के रूप में माना जा सकता है

C ++ 11 ने कॉन्स्टैक्सप्र क्रिया शुरू की जो:

कॉन्स्ट्रेक्स स्पेसियर यह घोषणा करता है कि संकलन समय पर फ़ंक्शन या चर के मूल्य का मूल्यांकन करना संभव है। इस तरह के चर और कार्यों का उपयोग तब किया जा सकता है जहां केवल संकलन समय स्थिर अभिव्यक्ति की अनुमति है।

जबकि C ++ 03 में कॉन्स्टैक्सप्रिसेस की सुविधा नहीं है, क्योंकि हमें कॉस्टेक्सप्राइस कीवर्ड का उपयोग करने की आवश्यकता नहीं है क्योंकि मानक लाइब्रेरी C ++ 11 में कॉन्स्टैक्स के रूप में कई फ़ंक्शन प्रदान करती है । उदाहरण के लिए std :: num_limits :: min । उदाहरण के लिए, विभिन्न व्यवहार हो सकते हैं:

#include <limits>

int main()
{
    int x[std::numeric_limits<unsigned int>::min()+2] ;
}

clangC ++ 03 का उपयोग xकरने से यह एक परिवर्तनशील लंबाई सरणी बन जाएगा , जो एक विस्तार है और निम्नलिखित चेतावनी उत्पन्न करेगा:

warning: variable length arrays are a C99 feature [-Wvla-extension]
    int x[std::numeric_limits<unsigned int>::min()+2] ;
         ^

जबकि C ++ 11 std::numeric_limits<unsigned int>::min()+2में एक संकलन समय स्थिर अभिव्यक्ति है और इसे वीएलए विस्तार की आवश्यकता नहीं है।

6. C ++ 11 में अपवाद अपवाद विशिष्ट रूप से आपके विध्वंसक के लिए उत्पन्न होते हैं

चूंकि C ++ 11 उपयोगकर्ता परिभाषित डिस्ट्रॉक्टरnoexcept(true) में निहित विनिर्देशन है जैसा कि noexcept डिस्ट्रक्टर्स में बताया गया है इसका मतलब है कि निम्नलिखित कार्यक्रम:

#include <iostream>
#include <stdexcept>

struct S
{
  ~S() { throw std::runtime_error(""); } // bad, but acceptable
};

int main()
{
  try { S s; }
  catch (...) {
    std::cerr << "exception occurred";
  } 
 std::cout << "success";
}

C ++ 11 में कॉल करेगा std::terminateलेकिन C ++ 03 में सफलतापूर्वक चलेगा।

7. C ++ 03 में, टेम्पलेट तर्क में आंतरिक संबंध नहीं हो सकता है

यह क्यों std में अच्छी तरह से कवर किया गया है :: सॉर्ट स्वीकार नहीं करता है एक फ़ंक्शन के भीतर घोषित वर्गों की तुलना करें । तो निम्नलिखित कोड C ++ 03 में काम नहीं करना चाहिए:

#include <iostream>
#include <vector>
#include <algorithm>

class Comparators
{
public:
    bool operator()(int first, int second)
    {
        return first < second;
    }
};

int main()
{
    class ComparatorsInner : public Comparators{};

    std::vector<int> compares ;
    compares.push_back(20) ;
    compares.push_back(10) ;
    compares.push_back(30) ;

    ComparatorsInner comparatorInner;
    std::sort(compares.begin(), compares.end(), comparatorInner);

    std::vector<int>::iterator it;
    for(it = compares.begin(); it != compares.end(); ++it)
    {
        std::cout << (*it) << std::endl;
    }
}

लेकिन वर्तमान में clangइस कोड को चेतावनी के साथ C ++ 03 मोड में अनुमति देता है जब तक कि आप -pedantic-errorsध्वज का उपयोग नहीं करते हैं , जो कि icky है, इसे लाइव देखें

8. कई टेम्प्लेटों को बंद करते समय वह बीमार नहीं होता है

>>कई टेम्प्लेट बंद करने का उपयोग करना अब बीमार नहीं है, लेकिन C ++ 03 और C + 11 में विभिन्न परिणामों के साथ कोड को जन्म दे सकता है। नीचे दिए गए उदाहरण को सही कोण कोष्ठक और पीछे की संगतता से लिया गया है :

#include <iostream>
template<int I> struct X {
  static int const c = 2;
};
template<> struct X<0> {
  typedef int c;
};
template<typename T> struct Y {
  static int const c = 3;
};
static int const c = 4;
int main() {
  std::cout << (Y<X<1> >::c >::c>::c) << '\n';
  std::cout << (Y<X< 1>>::c >::c>::c) << '\n';
}

और C ++ 03 में परिणाम है:

0
3

और C ++ 11 में:

0
0

9. सी ++ 11 एसटीडी के कुछ परिवर्तन :: वेक्टर कंस्ट्रक्टर

इस उत्तर से थोड़ा संशोधित कोड दिखाता है कि std से निम्न निर्माणकर्ता का उपयोग कर :: वेक्टर :

std::vector<T> test(1);

C ++ 03 और C ++ 11 में अलग-अलग परिणाम उत्पन्न करता है:

#include <iostream>
#include <vector>

struct T
{
    bool flag;
    T() : flag(false) {}
    T(const T&) : flag(true) {}
};


int main()
{
    std::vector<T> test(1);
    bool is_cpp11 = !test[0].flag;

    std::cout << is_cpp11 << std::endl ;
}

10. शुरुआती इनिशियलाइज़र में रूपांतरणों को कम करना

C ++ 11 में एग्रीगेट इनिशियलाइज़र में एक संकरा रूपांतरण बीमार है और ऐसा लगता है gccकि यह C ++ 11 और C ++ 03 दोनों में इसकी अनुमति देता है, हालांकि यह C ++ 11 में डिफ़ॉल्ट रूप से एक चेतावनी प्रदान करता है:

int x[] = { 2.0 };

यह C ++ 11 मानक अनुभाग 8.5.4 सूची-आरंभ पैराग्राफ 3 के मसौदे में शामिल है :

किसी वस्तु या प्रकार T के संदर्भ की सूची को इस प्रकार परिभाषित किया गया है:

और निम्नलिखित बुलेट ( जोर मेरा ) में शामिल हैं:

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

यह और कई और उदाहरण C ++ मानक अनुभाग annex C.2 C ++ और ISO C ++ 2003 के मसौदे में शामिल हैं । इसमें ये भी शामिल हैं:

  • नए प्रकार के स्ट्रिंग शाब्दिक [...] विशेष रूप से, आर, यू 8, यू 8 आर, यू, यूआर, यू, यूआर, या एलआर नामक मैक्रो का विस्तार नहीं किया जाएगा जब एक स्ट्रिंग शाब्दिक के निकट होगा, लेकिन स्ट्रिंग शाब्दिक के हिस्से के रूप में व्याख्या की जाएगी। । उदाहरण के लिए

    #define u8 "abc"
    const char *s = u8"def"; // Previously "abcdef", now "def"
    
  • उपयोगकर्ता-परिभाषित शाब्दिक स्ट्रिंग समर्थन [...] पहले, # 1 में दो अलग-अलग प्रीप्रोसेसिंग टोकन शामिल होंगे और मैक्रो _x का विस्तार किया गया होगा। इस अंतर्राष्ट्रीय मानक में, # 1 में एकल प्रीप्रोसेसिंग टोकन होते हैं, इसलिए मैक्रो का विस्तार नहीं किया जाता है।

    #define _x "there"
    "hello"_x // #1
  • पूर्णांक / और% [...] 2003 कोड के पूर्णांक विभाजन के परिणामों को निर्दिष्ट करें, जो पूर्णांक विभाजन का उपयोग करता है परिणाम को 0 या नकारात्मक अनंत की ओर ले जाता है, जबकि यह अंतर्राष्ट्रीय मानक हमेशा परिणाम को 0 की ओर गोल करता है।

  • आकार की जटिलता () सदस्य कार्य अब निरंतर [...] कुछ कंटेनर कार्यान्वयन जो C ++ 2003 के अनुरूप हैं, वे इस अंतर्राष्ट्रीय मानक में निर्दिष्ट आकार () आवश्यकताओं के अनुरूप नहीं हो सकते हैं। कंटेनरों को समायोजित करना जैसे std :: कड़ी आवश्यकताओं के लिए सूची में असंगत परिवर्तन की आवश्यकता हो सकती है।

  • Std का बेस क्लास बदलें :: ios_base :: विफलता [...] std :: ios_base :: विफलता अब सीधे std से नहीं निकली है :: अपवाद, लेकिन अब std से ली गई है :: system_error, जो बदले में से ली गई है std :: runtime_error। मान्य C ++ 2003 कोड जो मानता है कि std :: ios_base :: विफलता सीधे std से ली गई है :: अपवाद इस अंतर्राष्ट्रीय मानक में अलग तरह से निष्पादित हो सकता है।


इसलिए अधिकांश उदाहरण इस तथ्य से कम हैं कि पहले अपरिभाषित व्यवहार अब अच्छी तरह से परिभाषित है?
MatthiasB

@ मैथियासबी 2, 3 और 4 इस बारे में हैं, इसलिए वे इस उदाहरण का एक हिस्सा नहीं हैं। मुझे संदेह है कि मुझे कई अपरिभाषित व्यवहार के उदाहरण मिलेंगे, जैसे कि मैं और जोड़ूंगा तो वे एक छोटे से सेट बन जाएंगे।
शफीक याघमौर

खैर, # 1 व्यवहार अनिर्दिष्ट है, इसलिए मैं इसे अपरिभाषित व्यवहार के रूप में गिनाऊंगा (कम से कम आप c ++ 03 के साथ एक विशिष्ट परिणाम प्राप्त करने की उम्मीद नहीं कर सकते, अब c ++ 11 के साथ आप कर सकते हैं), # 5 एक गैर का उपयोग करता है c ++ का मानक विस्तार। लेकिन मुझे लगता है कि तुम सही हो। जितना अधिक आप इसे खोजते हैं, उतने अधिक उदाहरण आपको मिलेंगे जो दोनों मानकों में परिभाषित हैं, लेकिन अलग-अलग परिणाम देते हैं।
मथियासबी

@ मैथियासबी हाँ, अनिर्दिष्ट और अपरिभाषित व्यवहार के अवांछनीय परिणाम हैं। लिनक्स पर विचार करने वाले एक्सटेंशन के लिए कई प्रकार के जीसीसी एक्सटेंशन पर निर्भर करते हैं जिन्हें हमें वास्तविक दुनिया में वे मान लेना चाहिए। जब मैंने पहली बार इस प्रश्न का उत्तर दिया था तो मुझे इतने सारे उदाहरण मिलने की उम्मीद नहीं थी।
शफीक यघमौर

35

एक संभावित खतरनाक पिछड़ा-असंगत परिवर्तन अनुक्रम कंटेनरों के कंस्ट्रक्टरों में है std::vector, जैसे कि विशेष रूप से अधिभार में प्रारंभिक आकार निर्दिष्ट करना। जहाँ C ++ 03 में, उन्होंने एक डिफ़ॉल्ट-निर्मित तत्व की प्रतिलिपि बनाई, C ++ 11 में वे प्रत्येक एक डिफ़ॉल्ट-निर्माण करते हैं।

इस उदाहरण पर विचार करें (इसका उपयोग करके boost::shared_ptrयह मान्य C ++ 03 है):

#include <deque>
#include <iostream>

#include "boost/shared_ptr.hpp"


struct Widget
{
  boost::shared_ptr<int> p;

  Widget() : p(new int(42)) {}
};


int main()
{
  std::deque<Widget> d(10);
  for (size_t i = 0; i < d.size(); ++i)
    std::cout << "d[" << i << "] : " << d[i].p.use_count() << '\n';
}

C ++ 03 लाइव उदाहरण

C ++ 11 लाइव उदाहरण

इसका कारण यह है कि C ++ 03 ने "निर्दिष्ट आकार और प्रोटोटाइप तत्व" और "केवल आकार निर्दिष्ट करें" दोनों के लिए एक अधिभार निर्दिष्ट किया है, इस तरह (आवंटन तर्क, संक्षिप्तता के लिए छोड़ा गया):

container(size_type size, const value_type &prototype = value_type());

यह हमेशा prototypeकंटेनर sizeसमय में कॉपी होगा । जब इसे केवल एक तर्क के साथ कहा जाता है, तो यह sizeडिफ़ॉल्ट रूप से निर्मित तत्व की प्रतियां बनाएगा ।

C ++ 11 में, इस निर्माता के हस्ताक्षर को हटा दिया गया था और इन दो अधिभार के साथ बदल दिया गया था:

container(size_type size);

container(size_type size, const value_type &prototype);

दूसरा पहले की तरह काम करता है, तत्व sizeकी प्रतियां बनाता है prototype। हालाँकि, पहले वाला (जो अब केवल निर्दिष्ट आकार तर्क के साथ कॉल को हैंडल करता है) प्रत्येक तत्व को व्यक्तिगत रूप से डिफ़ॉल्ट-निर्माण करता है।

इस परिवर्तन के कारण के लिए मेरा अनुमान है कि C ++ 03 अधिभार केवल-चालित तत्व प्रकार के साथ प्रयोग करने योग्य नहीं होगा। लेकिन यह एक परिवर्तन कम नहीं है, और एक शायद ही कभी उस पर प्रलेखित है।


3
हालांकि यह स्पष्ट रूप से एक परिवर्तन है, मैं C ++ 11 व्यवहार को पसंद करता हूं। मुझे उम्मीद है dequeकि एक ही संसाधन साझा करने वाले दस विगेट्स नहीं बल्कि दस अलग-अलग विजेट होंगे।
एजेंटलीयन

19

एक से पढ़ने में विफल परिणाम std::istreamबदल गया है। CppReference इसे संक्षेप में प्रस्तुत करता है:

यदि निष्कर्षण विफल हो जाता है (उदाहरण के लिए यदि एक पत्र दर्ज किया गया था जहां एक अंक अपेक्षित है), valueअनमॉडिफाइड छोड़ दिया failbitजाता है और सेट किया जाता है। (C ++ 11 तक)

यदि निष्कर्षण विफल हो जाता है, तो शून्य को लिखा valueऔर failbitसेट किया जाता है। यदि मान में निष्कर्षण परिणाम बहुत बड़ा या बहुत छोटा होता है value, जिसमें फिट किया जाता है std::numeric_limits<T>::max()या std::numeric_limits<T>::min()लिखा जाता है और failbitध्वज सेट किया जाता है। (सी ++ 11 के बाद से)

यह मुख्य रूप से एक मुद्दा है यदि आप नए शब्दार्थ के लिए उपयोग किए जाते हैं और फिर C ++ 03 का उपयोग करके लिखना होगा। निम्नलिखित विशेष रूप से अच्छा अभ्यास नहीं है लेकिन C ++ 11 में अच्छी तरह से परिभाषित किया गया है:

int x, y;
std::cin >> x >> y;
std::cout << x + y;

हालाँकि, C ++ 03 में, उपरोक्त कोड एक uninitialized चर का उपयोग करता है और इस प्रकार अपरिभाषित व्यवहार होता है।


4
आप जोड़ सकते हैं, कि C ++ 03 में डिफ़ॉल्ट मान प्रदान करने के लिए इस मानकीकृत व्यवहार का उपयोग किया जा सकता है int x = 1, y = 1; cin >> x >> y; cout << x*y;। C ++ 03 के साथ, यह सही ढंग से उत्पन्न होगा xजब कोई yपढ़ा नहीं जा सकता है।
विस्फ़ोटक - मोनिका

15

यह थ्रेड , C ++ 03 और C ++ 0x के बीच किसी भी तरह के अंतर को रन-टाइम पर पता लगाया जा सकता है, भाषा के अंतर को निर्धारित करने के लिए उदाहरण (उस थ्रेड से कॉपी किए गए) हैं, उदाहरण के लिए C ++ 11 रेफरेंस को नष्ट करके।

template <class T> bool f(T&) {return true; } 
template <class T> bool f(...){return false;} 

bool isCpp11() 
{
    int v = 1;
    return f<int&>(v); 
}

और c ++ 11 स्थानीय प्रकारों को टेम्पलेट मापदंडों के रूप में अनुमति देता है:

template <class T> bool cpp11(T)  {return true;} //T cannot be a local type in C++03
                   bool cpp11(...){return false;}

bool isCpp0x() 
{
   struct local {} var; //variable with local type
   return cpp11(var);
}

7

यहाँ एक और उदाहरण है:

#include <iostream>

template<class T>
struct has {
  typedef char yes;
  typedef yes (&no)[2];    
  template<int> struct foo;    
  template<class U> static yes test(foo<U::bar>*);      
  template<class U> static no  test(...);    
  static bool const value = sizeof(test<T>(0)) == sizeof(yes);
};

enum foo { bar };

int main()
{
    std::cout << (has<foo>::value ? "yes" : "no") << std::endl;
}

प्रिंटों:

Using c++03: no
Using c++11: yes

Coliru पर परिणाम देखें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.