স্টেড :: ভেক্টর ওভার আইট্রেটেশন: স্বাক্ষরিত বনাম স্বাক্ষরিত সূচক ভেরিয়েবল


469

সি ++ তে কোনও ভেক্টরের মাধ্যমে পুনরাবৃত্তি করার সঠিক উপায় কী?

এই দুটি কোড টুকরা বিবেচনা করুন, এটি একটি ভাল কাজ করে:

for (unsigned i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

এবং এটি:

for (int i=0; i < polygon.size(); i++) {
    sum += polygon[i];
}

যা উত্পন্ন করে warning: comparison between signed and unsigned integer expressions

আমি সি ++ এর বিশ্বে নতুন, সুতরাং unsignedভেরিয়েবলটি আমার কাছে কিছুটা ভীতিজনক মনে হয় এবং আমি জানি যে unsignedভেরিয়েবলগুলি সঠিকভাবে ব্যবহার না করা বিপজ্জনক হতে পারে, তাই - এটি কি সঠিক?


9
স্বাক্ষরবিহীন একটি সঠিক কারণ বহুভুজ.সাইজ () স্বাক্ষরবিহীন টাইপের। স্বাক্ষরযুক্ত অর্থ সর্বদা ইতিবাচক বা 0 এর অর্থ এটিই। সুতরাং যদি ভেরিয়েবলের ব্যবহার সর্বদা কেবল গণনাগুলির জন্য থাকে তবে স্বাক্ষরযুক্ত না হ'ল সঠিক পছন্দ।
অ্যাডাম ব্রাস

2
@ অ্যাডামব্রুস .size()টাইপ unsignedওরফে নয় unsigned int। এটা টাইপ std::size_t
আন্ডারস্কোর_

1
@ ভাণ্ডার_ডি সাইজ_টি স্বাক্ষরবিহীন জন্য একটি উপনাম।
অ্যাডাম ব্রাস

1
@ অ্যাডামব্রস নং std::size_tএকটি _ বাস্তবায়ন-সংজ্ঞায়িত টাইপইফ। স্ট্যান্ডার্ড দেখুন। আপনার বর্তমান বাস্তবায়নের std::size_tসমতুল্য হতে পারে unsigned, তবে এটি প্রাসঙ্গিক নয়। এটি ভান করার ফলে নন-পোর্টেবল কোড এবং অপরিজ্ঞাত আচরণ হতে পারে।
আন্ডারস্কোর_

2
@ এলএফ ... নিশ্চিত, যা সম্ভবত std::size_tঅনুশীলনে রয়েছে আপনি কি মনে করেন যে আমরা 6 বছরেরও বেশি সময় ধরে মন্তব্যের এই ঝলকানি প্রবাহে এখনও সমস্ত কিছু আবরণ করেছি?
আন্ডারস্কোর_ডি

উত্তর:


816

পিছনে পুনরাবৃত্তি করার জন্য এই উত্তরটি দেখুন

ফরোয়ার্ডগুলি ইটারেটিং প্রায় অভিন্ন। কেবলমাত্র বৃদ্ধি দ্বারা পুনরাবৃত্তকারী / অদলবদল হ্রাস পরিবর্তন করুন। আপনার পুনরাবৃত্তির পছন্দ করা উচিত। কিছু লোক আপনাকে std::size_tসূচক ভেরিয়েবল টাইপ হিসাবে ব্যবহার করতে বলে । তবে তা পোর্টেবল নয়। সর্বদা size_typeকনটেইনার টাইপডেফটি ব্যবহার করুন (আপনি যখন পূর্বে পুনরাবৃত্তির ক্ষেত্রে কেবল একটি রূপান্তর নিয়ে দূরে সরে যেতে পারেন, তবে এটি ব্যবহার করার সময় পশ্চাদপদ পুনরাবৃত্তির ক্ষেত্রে সমস্ত পথে ভুল হতে পারে std::size_t, ক্ষেত্রে std::size_tটাইপফের চেয়ে আরও বিস্তৃত হবে size_type) :


স্টাড :: ভেক্টর ব্যবহার করে

পুনরুক্তি ব্যবহার করে

for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
    /* std::cout << *it; ... */
}

গুরুত্বপূর্ণটি হ'ল, পুনরাবৃত্তিকারীদের জন্য সর্বদা উপসর্গ ইনক্রিমেন্ট ফর্মটি ব্যবহার করুন যার সংজ্ঞা আপনি জানেন না। এটি নিশ্চিত করবে যে আপনার কোডটি যথাসম্ভব জেনেরিকের মতো চলে।

ব্যাপ্তি সি ++ 11 ব্যবহার করা হচ্ছে

for(auto const& value: a) {
     /* std::cout << value; ... */

সূচকগুলি ব্যবহার করে

for(std::vector<int>::size_type i = 0; i != v.size(); i++) {
    /* std::cout << v[i]; ... */
}

অ্যারে ব্যবহার করে

পুনরুক্তি ব্যবহার করে

for(element_type* it = a; it != (a + (sizeof a / sizeof *a)); it++) {
    /* std::cout << *it; ... */
}

ব্যাপ্তি সি ++ 11 ব্যবহার করা হচ্ছে

for(auto const& value: a) {
     /* std::cout << value; ... */

সূচকগুলি ব্যবহার করে

for(std::size_t i = 0; i != (sizeof a / sizeof *a); i++) {
    /* std::cout << a[i]; ... */
}

পশ্চাদপটে পুনরাবৃত্তির উত্তরটি পড়ুন sizeof, তবে পদ্ধতির কী কী সমস্যা হতে পারে।


আকারের পয়েন্টার: পার্থক্য_ টাইপ ব্যবহার করা আরও পোর্টেবল হতে পারে। পুনরাবৃত্তকারীদের_পরিচালনা <উপাদান_প্রকার *> :: পার্থক্য_প্রকার চেষ্টা করুন। এটি এক ঘোষণাপত্রের
মুখর

উইলহেমটেল, আমি কিসের জন্য ডিফারেন্স টাইপ ব্যবহার করব? সাইজটি ফেরত দিতে সাইজ_টি সংজ্ঞায়িত করা হয়েছে :) আমি আপনাকে বুঝতে পারি না। যদি আমি একে অপরের থেকে পয়েন্টারগুলি বিয়োগ করতে পারি তবে ডিফারেন্স টাইপটি সঠিক পছন্দ হবে।
জোহানেস স্কাউব - লিটব

আপনি এই পোস্টে উল্লিখিত কৌশলটি ব্যবহার করে অ্যারেগুলিতে পুনরাবৃত্তি কাজ করবে না যদি সেই ফাংশনে পাস হওয়া অ্যারেতে কোনও ক্রিয়ায় পুনরাবৃত্তি করা হচ্ছে। কারণ আকারের অ্যারে কেবল আকারের পয়েন্টারটি ফিরিয়ে দেবে।
সিস্টেমসফল

1
@ নীলে আমি সম্মত যে স্বাক্ষরযুক্ত লুপ কাউন্টার ব্যবহার করা একটি খারাপ ধারণা। তবে যেহেতু স্ট্যান্ডার্ড লাইব্রেরি ইনডেক্স এবং আকারের জন্য স্বাক্ষরবিহীন পূর্ণসংখ্যার ধরণের ব্যবহার করে, আমি স্ট্যান্ডার্ড লাইব্রেরির জন্য স্বাক্ষরবিহীন সূচি প্রকারগুলি পছন্দ করি। অন্যান্য লাইব্রেরিগুলি ফলস্বরূপ শুধুমাত্র Qt lib এর মতো স্বাক্ষরিত প্রকারগুলি ব্যবহার করে।
জোহানেস স্কাউব - লিটব

32
সি ++ 11 এর জন্য আপডেট: লুপের উপর ভিত্তি করে ব্যাপ্তি। for (auto p : polygon){sum += p;}
সিয়ুয়ান রেন

170

চার বছর কেটে গেছে, গুগল আমাকে এই উত্তর দিয়েছে। সঙ্গে মান সি ++ 11 (ওরফে সি ++ 0x নতুন:) সেখানে আসলে (অনুন্নত সহাবস্থানযোগ্যতা ভঙ্গ বিনিময়ে) এই কাজ করার একটি নতুন মনোরম উপায় autoশব্দ। এটি স্পষ্টভাবে ব্যবহার করার জন্য পুনরাবৃত্তির ধরণটি (ভেক্টর টাইপটি পুনরাবৃত্তি করা) নির্দিষ্ট করে দেওয়ার ব্যথা বাঁচায়, যখন এটি স্পষ্টভাবে (সংকলকের কাছে) ব্যবহার করতে হবে। সঙ্গে vআপনার হচ্ছে vector, আপনি ভালো কিছু করতে পারেন:

for ( auto i = v.begin(); i != v.end(); i++ ) {
    std::cout << *i << std::endl;
}

সি ++ 11 আরও আরও এগিয়ে যায় এবং আপনাকে ভেক্টরগুলির মতো সংগ্রহগুলিতে পুনরাবৃত্তি করার জন্য একটি বিশেষ সিনট্যাক্স দেয়। এটি সর্বদা একইরকম জিনিস লেখার প্রয়োজনীয়তা সরিয়ে দেয়:

for ( auto &i : v ) {
    std::cout << i << std::endl;
}

এটি একটি কার্যকারী প্রোগ্রামে দেখতে, একটি ফাইল তৈরি করুন auto.cpp:

#include <vector>
#include <iostream>

int main(void) {
    std::vector<int> v = std::vector<int>();
    v.push_back(17);
    v.push_back(12);
    v.push_back(23);
    v.push_back(42);
    for ( auto &i : v ) {
        std::cout << i << std::endl;
    }
    return 0;
}

এটি লেখার ক্ষেত্রে, আপনি যখন এটি g ++ দিয়ে সংকলন করেন, তখন আপনাকে সাধারণত একটি অতিরিক্ত পতাকা দিয়ে নতুন মানের সাথে কাজ করার জন্য সেট করতে হয়:

g++ -std=c++0x -o auto auto.cpp

এখন আপনি উদাহরণ চালাতে পারেন:

$ ./auto
17
12
23
42

দয়া করে নোট করুন যে সংকলন এবং চলমান সম্পর্কিত নির্দেশাবলী লিনাক্সে gnu c ++ সংকলক সম্পর্কিত , প্রোগ্রামটি প্ল্যাটফর্ম (এবং সংকলক) স্বতন্ত্র হওয়া উচিত।


7
সি ++ 11 আপনাকে দেয়for (auto& val: vec)
ফ্লেক্সো

@ ফ্লেক্সো ধন্যবাদ, আমি জানি না কীভাবে আমি এটি ভুলে যেতে পারি। যথেষ্ট সি ++ না করা, আমার ধারণা। বিশ্বাসযোগ্য হতে পারে না এমন ব্যবহারিক কিছু রয়েছে (ভাবা যা জাভাস্ক্রিপ্ট সিনট্যাক্স, আসলে)। আমি অন্তর্ভুক্ত উত্তর পরিবর্তন।
কারাতেঙ্কো

আপনার উত্তর খুব সুন্দর। এটি অসন্তুষ্ট যে বিভিন্ন ওএস ডেভিটসে জি ++ এর ডিফল্ট সংস্করণটি ৪.৩ এর নিচে রয়েছে যা এটি কাজ করে না।
রাতটা টাটা

আপনার কি ভেক্টর দিয়ে আরম্ভ করার দরকার আছে std::vector<int> v = std::vector<int>();, না আপনি এর std::vector<int> v;পরিবর্তে কেবল ব্যবহার করতে পারতেন ?
বিল চ্যাথাম

@ বিলচিথাম ভাল - আমি আরম্ভ না করেই চেষ্টা করেছি, এবং এটি কাজ করেছে, সুতরাং মনে হয় এটি ব্যতীত কার্যকর হয়।
kratenko

44

আপনার উদাহরণের নির্দিষ্ট ক্ষেত্রে, আমি এটি সম্পাদন করতে এসটিএল অ্যালগরিদম ব্যবহার করব।

#include <numeric> 

sum = std::accumulate( polygon.begin(), polygon.end(), 0 );

আরও সাধারণ, তবে এখনও মোটামুটি সহজ ক্ষেত্রে, আমি সাথে যাব:

#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

using namespace boost::lambda;
std::for_each( polygon.begin(), polygon.end(), sum += _1 );

38

জোহানেস স্কাউবের উত্তর সম্পর্কে:

for(std::vector<T*>::iterator it = v.begin(); it != v.end(); ++it) { 
...
}

এটি কিছু সংকলকগুলির সাথে কাজ করতে পারে তবে জিসিসির সাথে নয়। এখানে সমস্যাটি যদি std :: ভেক্টর :: পুনরুক্তিকারী একটি প্রকার, একটি ভেরিয়েবল (সদস্য) বা একটি ফাংশন (পদ্ধতি) হয় তবে তা প্রশ্ন। আমরা জিসিসি দিয়ে নিম্নলিখিত ত্রুটিটি পেয়েছি:

In member function void MyClass<T>::myMethod()’:
error: expected `;' before ‘it’
error: ‘it’ was not declared in this scope
In member function ‘void MyClass<T>::sort() [with T = MyClass]’:
instantiated from ‘void MyClass<T>::run() [with T = MyClass]’
instantiated from here
dependent-name ‘std::vector<T*,std::allocator<T*> >::iterator’ is parsed as a non-type, but instantiation yields a type
note: say ‘typename std::vector<T*,std::allocator<T*> >::iterator’ if a type is meant

সমাধানটি 'টাইপনেম' কীওয়ার্ডটি যেমন বলেছে তেমন ব্যবহার করছে:

typename std::vector<T*>::iterator it = v.begin();
for( ; it != v.end(); ++it) {
...

2
আপনার বিশদভাবে বলা উচিত যে এটি কেবল তখনই প্রযোজ্য যখন Tকোনও টেম্পলেট আর্গুমেন্ট হয়, এবং এইভাবে এক্সপ্রেশনটি std::vector<T*>::iteratorএকটি নির্ভরশীল নাম। নির্ভরশীল নামটিকে টাইপ হিসাবে পার্স করার জন্য typename, ডায়াগনস্টিকটি ইঙ্গিত করে বলে কীওয়ার্ড দ্বারা এটি চাপানো দরকার ।
মনিকা

17

একটি কল vector<T>::size()প্রকারের std::vector<T>::size_type, মানহীন, স্বাক্ষরবিহীন ইন্ট বা অন্যথায় নয় এমন ধরণের মান প্রদান করে ।

এছাড়াও সাধারণত সি ++ এর একটি ধারক ধরে পুনরাবৃত্তি ব্যবহার করে করা হয় পুনরুক্তিগুলি

std::vector<T>::iterator i = polygon.begin();
std::vector<T>::iterator end = polygon.end();

for(; i != end; i++){
    sum += *i;
}

যেখানে টি ভেক্টরে আপনি যে ধরণের ডেটা সঞ্চয় করেন তা হ'ল।

বা বিভিন্ন পুনরাবৃত্তির আলগোরিদিম ব্যবহার ( std::transform, std::copy, std::fill, std::for_eachইত্যাদি)।


আইট্রেটাররা সাধারণত একটি ভাল ধারণা, যদিও আমি সন্দেহ করি যে একটি পৃথক ভেরিয়েবলে "শেষ" সংরক্ষণ করার প্রয়োজন আছে এবং এটি সমস্ত একটি (;;) বিবৃতিতে করা যেতে পারে।
সাওলিয়াস maemaitaitis 17

1
আমি জানি (শুরু) এবং শেষ () অবিচ্ছিন্ন ধ্রুবক সময়, তবে আমি সাধারণত সবকিছুকে এক লাইনে ক্র্যাম করার চেয়ে এটি আরও বেশি পঠনযোগ্য বলে মনে করি।
জ্যাস্পার বেকারস 17

3
পাঠযোগ্যতা উন্নত করতে আপনি আলাদা লাইনগুলিতে ভাগ করতে পারেন। লুপের বাইরে পুনরুক্তি ঘোষণার অর্থ আপনার প্রতিটি লুপের জন্য বিভিন্ন ধরণের কন্টেইনারগুলির জন্য পৃথক পুনরাবৃত্তির নাম প্রয়োজন।
জে কনরোড

আমি সমস্ত পার্থক্য সম্পর্কে অবগত এবং এটি মূলত যা নেমে আসে তা ব্যক্তিগত পছন্দ; আমি সাধারণত জিনিসগুলি এভাবেই শেষ করি।
জ্যাস্পার বেকারস

2
@ পাইহেনতাগি আমার ধারণা যে এটি ফর-লুপের প্রথম বিভাগে স্থাপন করা হবে। যেমন। (স্বতঃ i = বহুভুজ.বেগিন (), শেষ = বহুভুজন.এন্ড (); i! = শেষ; i ++)
জ্যাস্পার বেকারস

11

ব্যবহার size_t:

for (size_t i=0; i < polygon.size(); i++)

উইকিপিডিয়া উদ্ধৃত :

Stdlib.h এবং stddef.h শিরোলেখ ফাইলগুলি একটি ডেটাটাইপ নামক সংজ্ঞা দেয় size_tযা কোন বস্তুর আকারকে উপস্থাপন করতে ব্যবহৃত হয়। আকার ধারণ করে এমন লাইব্রেরির ফাংশনগুলি তাদের প্রকারের প্রত্যাশা করে size_tএবং আকারটি অপারেটর মূল্যায়ন করে size_t

প্রকৃত ধরণ size_tহ'ল প্ল্যাটফর্ম নির্ভর; একটি সাধারণ ভুল হ'ল size_tস্বাক্ষরযুক্ত স্বাক্ষর হিসাবে একই, যা প্রোগ্রামিং ত্রুটি হতে পারে, বিশেষত 64৪-বিট আর্কিটেকচার আরও প্রচলিত হয়ে ওঠে বলে।


সাইজ_টি ভেক্টরের জন্য ঠিক আছে, কারণ এটি অবশ্যই অবশ্যই সমস্ত বস্তুকে একটি অ্যারেতে জমা করতে হবে (নিজেই একটি বস্তুও) তবে একটি স্টাড :: তালিকায় আকার_t উপাদানগুলির চেয়ে বেশি থাকতে পারে!
এমসাল্টারস

1
আকার_t একটি প্রক্রিয়ার ঠিকানা স্পেসে সমস্ত বাইট গণনা করার জন্য যথেষ্ট পর্যাপ্ত। যদিও আমি দেখতে পাচ্ছি যে এটি কিছু বিদেশী আর্কিটেকচারের ক্ষেত্রে কীভাবে না ঘটে, আমি বরং এটি নিয়ে চিন্তা করব না।

আমি যতদূর জানি এটি সুপারিশ করা হচ্ছে #include <cstddef>বদলে <stddef.h>বা, তার থেকেও খারাপ, সম্পূর্ণতা [c]stdlib, এবং ব্যবহার std::size_tবদলে অযোগ্য সংস্করণ - যেখানে আপনার মধ্যে একটা চয়েস থাকে অন্য কোন পরিস্থিতির জন্য এবং একই <cheader>এবং <header.h>
আন্ডারস্কোর_২

7

ইতিহাসের একটি বিট:

একটি নম্বর নেতিবাচক কিনা তা উপস্থাপন করতে কম্পিউটার একটি 'সাইন' বিট ব্যবহার করে। intএটি একটি স্বাক্ষরিত ডেটা ধরণের অর্থ এটি ইতিবাচক এবং নেতিবাচক মানগুলি ধরে রাখতে পারে (প্রায় -2 বিলিয়ন থেকে 2 বিলিয়ন)। Unsignedকেবল ধনাত্মক সংখ্যা সঞ্চয় করতে পারে (এবং যেহেতু এটি মেটাডেটাতে কিছুটা অপচয় করে না এটি আরও বেশি সঞ্চয় করতে পারে: 0 থেকে প্রায় 4 বিলিয়ন)।

std::vector::size()একটি ফেরৎ unsigned, কিভাবে একটি ভেক্টর নেতিবাচক দৈর্ঘ্য হতে পারে জন্য?

সতর্কতা আপনাকে বলে দিচ্ছে যে আপনার অসমতার বিবৃতিটির ডান ক্রিয়াকলাপটি তখন বামদিকে আরও ডেটা ধরে রাখতে পারে।

মূলত যদি আপনার 2 বিলিয়ন এরও বেশি প্রবেশদ্বার সহ একটি ভেক্টর থাকে এবং আপনি ওভারফ্লো সমস্যাগুলিকে আঘাত করতে পারেন তবে সূচকটির জন্য একটি পূর্ণসংখ্যার ব্যবহার করেন (ইতিপূর্বে নেতিবাচক 2 বিলিয়ন হয়ে যাবে)।


6

আমি সাধারণত BOOST_FOREach ব্যবহার করি:

#include <boost/foreach.hpp>

BOOST_FOREACH( vector_type::value_type& value, v ) {
    // do something with 'value'
}

এটি এসটিএল পাত্রে, অ্যারে, সি-স্টাইলের স্ট্রিং ইত্যাদিতে কাজ করে


2
অন্য কিছু প্রশ্নের ভাল উত্তর (আমি কীভাবে কোনও ভেক্টরকে পুনরায় করবো?), তবে ওপি কী জিজ্ঞাসা করছিল তা পুরোপুরি নয় (স্বাক্ষরযুক্ত ভেরিয়েবল সম্পর্কে সতর্কতার অর্থ কী?)
অ্যাবেলেঙ্কি

3
ঠিক আছে, তিনি জিজ্ঞাসা করেছিলেন কোনও ভেক্টর দিয়ে পুনরাবৃত্তি করার সঠিক উপায় কি। তাই যথেষ্ট প্রাসঙ্গিক বলে মনে হচ্ছে। সতর্কবাণী হ'ল তিনি কেন তার বর্তমান সমাধানটিতে সন্তুষ্ট নন।
জাল্ফ

5

সম্পূর্ণ হতে, সি ++ 11 সিনট্যাক্স পুনরাবৃত্তির ( রেফ ) জন্য কেবল একটি অন্য সংস্করণ সক্ষম করে :

for(auto it=std::begin(polygon); it!=std::end(polygon); ++it) {
  // do something with *it
}

যা বিপরীত পুনরাবৃত্তির জন্যও আরামদায়ক

for(auto it=std::end(polygon)-1; it!=std::begin(polygon)-1; --it) {
  // do something with *it
}

5

সি ++ 11 এ

আমি সাধারণ অ্যালগরিদম পছন্দ করি for_eachঅতিরিক্ত নামযুক্ত ফাংশন / অবজেক্টগুলি এড়ানোর জন্য সঠিক ধরণের পুনরুক্তি এবং ল্যাম্বডা এক্সপ্রেশনটি অনুসন্ধান এড়াতে পছন্দ করব।

আপনার বিশেষ ক্ষেত্রে (বহুভুজটি পূর্ণসংখ্যার ভেক্টর হিসাবে ধরে নেওয়া) এর সংক্ষিপ্ত "সুন্দর" উদাহরণ:

for_each(polygon.begin(), polygon.end(), [&sum](int i){ sum += i; });

পরীক্ষিত: http://ideone.com/i6Ethd

অন্তর্ভুক্ত করতে ভুলবেন না : অ্যালগরিদম এবং, অবশ্যই, ভেক্টর :)

মাইক্রোসফ্ট প্রকৃতপক্ষে এ সম্পর্কে একটি দুর্দান্ত উদাহরণও দিয়েছে:
উত্স: http://msdn.microsoft.com/en-us/library/dd293608.aspx

#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;

int main() 
{
   // Create a vector object that contains 10 elements.
   vector<int> v;
   for (int i = 1; i < 10; ++i) {
      v.push_back(i);
   }

   // Count the number of even numbers in the vector by 
   // using the for_each function and a lambda.
   int evenCount = 0;
   for_each(v.begin(), v.end(), [&evenCount] (int n) {
      cout << n;
      if (n % 2 == 0) {
         cout << " is even " << endl;
         ++evenCount;
      } else {
         cout << " is odd " << endl;
      }
   });

   // Print the count of even numbers to the console.
   cout << "There are " << evenCount 
        << " even numbers in the vector." << endl;
}

4
for (vector<int>::iterator it = polygon.begin(); it != polygon.end(); it++)
    sum += *it; 

2
ভেক্টরের পক্ষে এটি ভাল, তবে পুনরাবৃত্তকারীটি যদি তুচ্ছ-তুচ্ছ হয় তবে সাধারণভাবে এটি ++ এর চেয়ে এটি ++ ব্যবহার করা ভাল।
স্টিভ জেসোপ

ব্যক্তিগতভাবে, আমি ++ i ব্যবহার করতে অভ্যস্ত, তবে আমি মনে করি বেশিরভাগ লোকেরা i++ স্টাইল পছন্দ করেন ("for" এর জন্য ডিফল্ট ভিএস কোড স্নিপেটটি i ++)। কেবল একটি চিন্তা
মেহরদাদ আফশারি

@ মেহরদাদআফশারি "বেশিরভাগ লোক" কী করে কে যত্ন করে? "বেশিরভাগ লোক" প্রচুর জিনিস সম্পর্কে ভুল। পোস্ট-ইনক / হ্রাস যেখানে প্রাক মানটি কখনই ব্যবহার করা হয় না তা ভুল এবং অকার্যকর, কমপক্ষে তত্ত্বের ক্ষেত্রে - এটি সর্বত্র যে কোনও উপ-পার্ব উদাহরণ কোডে অন্ধভাবে ব্যবহৃত হয় তা নির্বিশেষে। যারা এখনও আরও ভাল জানেন না তাদের জিনিসগুলিকে আরও বেশি পরিচিত করার জন্য আপনার খারাপ অভ্যাসগুলি উত্সাহিত করা উচিত নয়।
আন্ডারস্কোর_

2

প্রথমটি সঠিক, এবং কিছু কঠোর অর্থে সঠিক type (আপনি যদি ভাবেন তবে আকারটি কখনই শূন্যের চেয়ে কম হতে পারে না)) যদিও এই সতর্কতা আমাকে অগ্রাহ্য করার জন্য একজন ভাল প্রার্থী হিসাবে আঘাত করে strikes


2
আমি মনে করি এটি অগ্রাহ্য করা একটি ভয়াবহ প্রার্থী - এটি ঠিক করা সহজ, এবং একবারে সত্যায়িত বাগগুলি স্বাক্ষরিত / স্বাক্ষরযুক্ত মানগুলিকে অনুপযুক্ত তুলনা করার কারণে ঘটে occur এই ক্ষেত্রে উদাহরণস্বরূপ, আকারটি INT_MAX এর চেয়ে বেশি হলে লুপটি কখনই শেষ হয় না।
স্টিভ জেসোপ

... অথবা সম্ভবত এটি অবিলম্বে বন্ধ হয়ে যায়। দুই এর মধ্যে এক. স্বাক্ষরিত মানটি তুলনা করার জন্য স্বাক্ষরিত রূপান্তরিত, না স্বাক্ষরিত স্বাক্ষরে রূপান্তরিত হয়েছে কিনা তা নির্ভর করে। 32 বিট ইনট সহ একটি 64 বিট প্ল্যাটফর্মে, যদিও উইন 64 এর মতো, ইন্টি সাইজ_টিতে উন্নীত হবে এবং লুপটি কখনই শেষ হয় না।
স্টিভ জেসোপ

@ স্টিভ জেসাপ: আপনি নিশ্চিতভাবে বলতে পারবেন না যে লুপটি কখনই শেষ হয় না। পুনরাবৃত্তির সময় যখন i == INT_MAX, তখন অপরিবর্তিত i++আচরণের কারণ হয়। এই সময়ে কিছু ঘটতে পারে।
বেন ভয়েগট

@ বেনওয়েগট: সত্য, এবং এখনও সতর্কবার্তাটিকে অগ্রাহ্য করার জন্য কোনও ভিত্তি সরবরাহ করে না :-)
স্টিভ জেসপ

2

আপনার আদৌ পুনরাবৃত্তি করতে হবে কিনা তা বিবেচনা করুন

<algorithm>মান হেডার এই জন্য সুবিধা সঙ্গে আমাদের প্রদান করে:

using std::begin;  // allows argument-dependent lookup even
using std::end;    // if the container type is unknown here
auto sum = std::accumulate(begin(polygon), end(polygon), 0);

অ্যালগরিদম গ্রন্থাগারের অন্যান্য ফাংশনগুলি সাধারণ কাজগুলি সম্পাদন করে - আপনি নিজের চেষ্টাটি সংরক্ষণ করতে চান তবে কী উপলব্ধ তা নিশ্চিত হয়ে নিন।


1

অস্পষ্ট কিন্তু গুরুত্বপূর্ণ বিশদ: আপনি যদি নীচের হিসাবে "(অটো এটি)" বলে থাকেন তবে আপনি বস্তুর অনুলিপি পাবেন, আসল উপাদানটি নয়:

struct Xs{int i} x;
x.i = 0;
vector <Xs> v;
v.push_back(x);
for(auto it : v)
    it.i = 1;         // doesn't change the element v[0]

ভেক্টরের উপাদানগুলি সংশোধন করতে, আপনাকে পুনরাবৃত্তিটিকে একটি রেফারেন্স হিসাবে সংজ্ঞায়িত করতে হবে:

for(auto &it : v)

1

যদি আপনার সংকলক এটি সমর্থন করে, আপনি ভেক্টর উপাদানগুলিতে অ্যাক্সেসের জন্য ভিত্তিক একটি পরিসীমা ব্যবহার করতে পারেন:

vector<float> vertices{ 1.0, 2.0, 3.0 };

for(float vertex: vertices){
    std::cout << vertex << " ";
}

প্রিন্টগুলি: 1 2 3। দ্রষ্টব্য, আপনি ভেক্টরের উপাদানগুলি পরিবর্তনের জন্য এই কৌশলটি ব্যবহার করতে পারবেন না।


0

দুটি কোড বিভাগ একই কাজ করে। তবে, স্বাক্ষরবিহীন ইন্ট "রুটটি সঠিক। স্বাক্ষরবিহীন ইনট প্রকারগুলি ব্যবহার করা ভেক্টরের সাথে আপনি যে উদাহরণটি ব্যবহার করেছেন সেটির সাথে আরও ভাল কাজ করবে a "i" এর নিজস্ব ধরণের একটি মান।

এছাড়াও, আপনি যদি আপনার কোডটিতে "স্বাক্ষরবিহীন অন্তর্নিহিত" কীভাবে দেখেন সে সম্পর্কে কিছুটা অস্বস্তি বোধ করেন তবে "uint" চেষ্টা করুন। এটি মূলত "স্বাক্ষরবিহীন ইন" এর একটি সংক্ষিপ্ত সংস্করণ এবং এটি ঠিক একইরকম কাজ করে। এটি ব্যবহারের জন্য আপনাকে অন্যান্য শিরোনামও অন্তর্ভুক্ত করার দরকার নেই।


আকার () এর জন্য স্বাক্ষরযুক্ত পূর্ণসংখ্যার অগত্যা সি ++ পদগুলিতে "স্বাক্ষরযুক্ত ইন্টি" এর সমান হয় না, প্রায়শই এই ক্ষেত্রে 'স্বাক্ষরবিহীন পূর্ণসংখ্যা' একটি 64 বিট স্বাক্ষরযুক্ত পূর্ণসংখ্যার হয় যখন 'স্বাক্ষরবিহীন আন্ত' সাধারণত 32 বিট হয়।
মাদারান

0

এটিকে যুক্ত করার জন্য আমি এটি কোনও উত্তরে উল্লেখ করে খুঁজে পাইনি: সূচক-ভিত্তিক পুনরাবৃত্তির জন্য, আমরা এটি ব্যবহার করতে পারি decltype(vec_name.size())যা মূল্যায়ন করবেstd::vector<T>::size_type

উদাহরণ

for(decltype(v.size()) i{ 0 }; i < v.size(); i++) {
    /* std::cout << v[i]; ... */
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.