2015-01-31 10 views
5

मैंने अभी कुछ सी ++ कोड देखा है। यह तय करने के लिए एक शर्त का उपयोग कर रहा था कि std::vector के माध्यम से आगे या पीछे चलना है या नहीं। संकलक शिकायत नहीं करता है, लेकिन मैंने सोचा कि size_t हस्ताक्षरित था। क्या यह खतरनाक है?क्या आकार_t के साथ नकारात्मक पूर्णांक का उपयोग करना सुरक्षित है?

vector<int> v { 1,2,3,4,5 };  
bool rev = true; 

size_t start, end, di; 
if (rev) { 
    start = v.size()-1; 
    end = -1; 
    di = -1; 
} 
else { 
    start = 0; 
    end = v.size(); 
    di = 1; 
} 

for (auto i=start; i!=end; i+=di) { 
    cout << v[i] << endl; 
} 
+1

मानक के रूप में' स्थिर स्थिरांक size_type एनपीओ = -1 'परिभाषित करता है std :: स्ट्रिंग :: npos'। Pedantic होने के लिए आप पसंद कर सकते हैं: 'std :: वेक्टर :: size_type प्रारंभ, अंत, di;'। – Galik

+0

@Galic: मैं यह देखने के लिए कि क्या पांडित्य (के रूप में आप यह कहते हैं) को प्राप्त होता है असफल, क्या लाभ यह एक मेंटेनर has.If 'एक संभाजक प्रावधान है कि साथ instantiating std :: vector' से बातें तोड़ने के लिए अपने या अपने रास्ते से बाहर चला जाता है एक मूर्ख आकार का प्रकार, जो पैडेंट्री करता है वह उस चीज को बढ़ाता है जिससे वह चीजों को झुकाव में सफल होता है। जैसा की मैं देख पा रहा हूँ। –

+0

@ चीयर्संधथ.-अल्फ ठीक है आप शायद सही हैं। जहां तक ​​मैं कह सकता हूं कि मानक कहता है कि 'std :: vector :: size_type' को हस्ताक्षरित किया जाना चाहिए, लेकिन मुझे लगता है कि यह' std :: size_t' के लिए एक अलग आकार हो सकता है। हालांकि मुझे लगता है कि अधिकांश कार्यान्वयन 'size_type' को 'size_t' जैसा ही बना देंगे। – Galik

उत्तर

6

यह अच्छी तरह से अहस्ताक्षरित पूर्णांकों का उपयोग करने के लिए निर्धारित किया है इस तरह से (और size_t अहस्ताक्षरित है), wraparound साथ: उस व्यवहार, के रूप में हस्ताक्षर किए पूर्णांकों के साथ करने का विरोध किया, मानक द्वारा गारंटीकृत है जहां यह है मानक द्वारा गारंटी नहीं है।

हालांकि यह बेकार में चतुर है। अहस्ताक्षरित के लिए निहित रैपिंग प्रोन्नति के कारण

एक सामान्य नियम के रूप में, से बचने के लिए समस्या है, थोड़ा-स्तरीय सामान के लिए अहस्ताक्षरित पूर्णांकों का उपयोग, उपयोग संख्या के लिए पूर्णांकों पर हस्ताक्षर किए। जहां आपको size_t से संबंधित एक हस्ताक्षरित पूर्णांक की आवश्यकता है, वहां आपके लिए ptrdiff_t है। हस्ताक्षरित परिणाम के साथ n_items फ़ंक्शन को परिभाषित करें, उदा।

using Size = ptrdiff_t; 

template< class Container > 
auto n_items(Container const& c) 
    -> Size 
{ return end(c) - begin(c); } 

और आप संकलक से जाने के लिए, कोई और अधिक sillywarnings तैयार हैं।


बहुत चालाक दिया कोड की बजाय

vector<int> v { 1,2,3,4,5 };  
bool rev = true; 

size_t start, end, di; 
if (rev) { 
    start = v.size()-1; 
    end = -1; 
    di = -1; 
} 
else { 
    start = 0; 
    end = v.size(); 
    di = 1; 
} 

for (auto i=start; i!=end; i+=di) { 
    cout << v[i] << endl; 

उदा करना

const vector<int> v { 1,2,3,4,5 };  
const bool reverse = true; // whatever 

for(int i = 0; i < n_items(v); ++i) 
{ 
    const int j = (reverse? n_items(v) - i - 1 : i); 
    cout << v[j] << endl; 
} 
0

यह size_t साथ नकारात्मक पूर्णांक उपयोग करने के लिए सुरक्षित है?

नहीं, यह खतरनाक है। ओवरफ्लो।

size_t a = -1; 
std::cout << a << "\n"; 

आउटपुट:

4294967295 // depends on the system, largest value possible here 
+1

यह खतरनाक अतिप्रवाह नहीं है, लेकिन अच्छी तरह से परिभाषित लपेटा है। Size_t पर नकारात्मक संख्याओं को कास्ट करना सामान्य रूप से आकार को वापस करने वाले कार्यों से त्रुटियों को वापस करने का एक आम तरीका है; सी मानक पुस्तकालय स्वयं उदाहरण के लिए 'mbrtoc32() 'जैसे कार्यों में करता है। – dpi

1

मैं से बात नहीं कर सकते हैं कि कैसे सुरक्षित कि कोड है, लेकिन मुझे लगता है कि यह एक बहुत गरीब शैली है। इटरेटर्स का उपयोग करने का एक बेहतर तरीका होगा जो आगे बढ़ने या पुनरावृत्ति को उलट देता है।

उदाहरण के लिए:

std::vector<int> v = { 1, 2, 3, 4, 5 }; 
bool rev = true; 

if (rev) 
{ 
    for (auto itr = v.rbegin(); itr != v.rend(); ++itr) 
    { 
     std::cout << *itr << "\n"; 
    } 
} 
else 
{ 
    for (auto itr = v.begin(); itr != v.end(); ++itr) 
    { 
     std::cout << *itr << "\n"; 
    } 
} 
+0

किसी भी तरह से कोड g ++ 4.8.2 के साथ संकलित नहीं करता है। क्या आप किसी भी कारण से सोच सकते हैं? –

+1

मुझे यकीन नहीं है (इसे इस तथ्य के साथ करना पड़ सकता है कि * rend() * और * शुरू() * एक ही प्रकार का मूल्यांकन नहीं करेगा)। यह एक वैचारिक उत्तर था; मैंने इसका परीक्षण नहीं किया। मैं वास्तव में संकलित कुछ के साथ अद्यतन करेंगे। –

0

जब भी मैं पर हस्ताक्षर किए प्रकार से निपटने के लिए की जरूरत है, मैं हमेशा का उपयोग करें:

typedef std::make_signed<std::size_t>::type ssize_t; // Since C++11 

... std को एक हस्ताक्षरित विकल्प :: size_t के रूप में।

मुझे खुशी इस सवाल का कुछ साल पुराना है, लेकिन मुझे लगता है कि दूसरों की मदद करेगा उम्मीद कर रहा हूँ। moodycamel::ConcurrentQueue पर क्रेडिट। `जो मूल रूप से एक समान चाल है,

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