সি ++ এসটিএল ভেক্টর: সূচক থেকে পুনরাবৃত্তি পাবেন?


200

সুতরাং, আমি একটি গুচ্ছ কোড লিখেছি যা সূচী দ্বারা একটি স্টিল ভেক্টরের উপাদানগুলিতে অ্যাক্সেস করে [], তবে এখন আমার কেবল ভেক্টরের একটি অংশের অনুলিপি করা দরকার। দেখে মনে vector.insert(pos, first, last)হচ্ছে এমন ফাংশনটি যা আমি চাই ... কেবলমাত্র আর্ট হিসাবে আমার প্রথম এবং শেষ নেই except এই মানগুলিতে আমি একটি পুনরাবৃত্তি পেতে পারে এমন কোনও ভাল উপায় আছে?


1
আরও দেখুন: stackoverflow.com/q/2152986/365102
Mateen Ulhaq

আমি যদি ভুল না করি তবে উত্তরের কোনও উত্তরই কোনও বাউন্ড চেক করে না, যা সমস্যা হতে পারে। বিশেষত, স্ট্যান্ড :: অগ্রিম ডক্স বলছে যে আপনি যদি অন্তর্নিহিত ধারক সীমার বাইরে যেতে ব্যবহার করেন তবে আচরণটি অপরিজ্ঞাত।
মার্টিন পেক্কা

উত্তর:


292

এটা চেষ্টা কর:

vector<Type>::iterator nth = v.begin() + index;

4
সাধারণত, আপনি পয়েন্টারগুলির চেয়ে এসটিএল পুনরাবৃত্তির সাথে একই গাণিতিক ব্যবহার করতে পারেন। এসটিএল অ্যালগরিদম ব্যবহার করার সময় এগুলি বিনিময়যোগ্য হিসাবে নকশাকৃত করা হয়।
ভিনসেন্ট রবার্ট

17
@ ভিনসেন্টরোবার্ট: অন্যভাবে। পয়েন্টারগুলি সবচেয়ে শক্তিশালী বিভাগ, এসটিএল র্যান্ডম পুনরাবৃত্তির বৈধ বাস্তবায়ন। তবে অন্যান্য, কম শক্তিশালী বিভাগ যেমন ফরোয়ার্ড ইটারেটরগুলি একই গাণিতিক সমর্থন করে না।
MSalters

6
আমি এই উত্তরে আমার পাঁচটি সেন্ট যুক্ত করতে এবং সুপারিশ করতে চাইstd::next(v.begin(), index)
stryku

86

@ ডিরেক্টর দ্বারা উল্লিখিত উপায়টি ভেক্টরদের ( v.begin() + index )জন্য দুর্দান্ত এবং দ্রুত

তবে সর্বাধিক জেনেরিক উপায় এবং এলোমেলো অ্যাক্সেসের পুনরাবৃত্তিগুলির জন্য ধ্রুবক সময়ও কাজ করে। std::advance( v.begin(), index )


ব্যবহারের মধ্যে সম্পাদনা পার্থক্য:

std::vector<>::iterator it = ( v.begin() + index );

অথবা

std::vector<>::iterator it = v.begin();
std::advance( it, index );

@ লিটব নোট পরে যুক্ত করা হয়েছে।


প্রথম আর্গুমেন্ট হিসাবে স্ট্যান্ড :: অগ্রিম কোনও নন-কনস্ট্রেট পুনরুক্তি প্রয়োজন?
গোল্ডপিউডো

আপনি স্ট্যান্ড :: অ্যাডভান্সড কনস্ট্যান্ড এবং নন-কনস্ট্যান্ট পুনরাবৃত্তকারীগুলির সাথে ব্যবহার করতে পারেন
বায়দা

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

1
আমি মনে করি সমস্যাটি "কনস্ট" এর অর্থ নিয়ে বিভ্রান্তি: আগাম () আনন্দের সাথে কনস্টেটিরেটরে কাজ করবে <T>, যা একটি পরিবর্তনীয় পুনরাবৃত্তি যা টাইপ টির একটি কনস্ট উপাদানকে বোঝায়; এটি কোনও পুনরাবৃত্ত বস্তুতে কাজ করবে না যা নিজেই কনস্ট (যেমন "কনস্ট পুনরুক্তি <T>" বা "পুনরাবৃত্তি <T> কনস্ট")।
j_random_hacker

7
আপনি যদি জানেন যে আপনি একটি নিয়ে কাজ করছেন তবে এটির std::vectorব্যবহার করার কোনও মানে নেই std::advance। এটি কেবল আপনাকে কনটেইনার-অজোনস্টিক কোড (যা আপনি করেন না, পুনরাবৃত্তকারী অবৈধকরণ বিধি, বিভিন্ন রানটাইম জটিলতা এবং কী নোটের কথা ভেবেছেন) তা লিখতে প্ররোচিত করে। std::advanceযখন আপনি নিজে একটি টেম্পলেট লেখেন তখন একমাত্র কেসটি যখন বুদ্ধিমান হয় তখন তা জানা যায় না যে এটি কী ধরণের পুনরুদ্ধারের সাথে কাজ করছে।
ফ্রেরিচ রাবাবে

47

এছাড়াও; auto it = std::next(v.begin(), index);

আপডেট: একটি সি ++ 11x অনুবর্তী সংকলক প্রয়োজন


2
এটি লক্ষ করা উচিত যে এটি সি ++ 11 টি উপায়! std :: এর পরের স্টাড :: অগ্রিমের সমান। পাটিগণিত ব্যবহার না করে এই ফাংশনগুলি ব্যবহার করে ধারক প্রকারের অদলবদলকে অনেক সহজ করে তোলে। এমনকি সিডি-অ্যারে আফাইকের উপরও কাজ করে, যেমন স্ট্যান্ড :: শুরু এবং স্ট্যান্ড :: শেষের মতো।
জুমুলেটর

2
এটিও লক্ষ করা উচিত যে স্টাড :: অগ্রিম একটি নির্বোধ দ্বারা ডিজাইন করা হয়েছে কারণ এটি আউটপুট হিসাবে কোনও রেফারেন্স ব্যবহার করে, না ফেরতের মান।
ভিক্টর সেহর

1
(অটো এটি = শুরু (সি); এটি! = শেষ (সি); অগ্রিম (এটি, এন)) এর জন্য {...}
জুমুলেটর

2
উভয়ের ব্যবহার আছে। stda :: অগ্রিম স্থানে পুনরুক্তি পরিবর্তনের জন্য দরকারী। এটি লুপগুলিতে পারফরম্যান্সের উদ্বেগ। আপনার পরামর্শ অনুসারে আমি নিয়োগের ক্ষেত্রে আরও পছন্দ করব। আমি এটি নির্বোধ বলে দাবী করে কিছুটা কঠোর বলেছি। উভয় ফাংশন মূলত একই রকম হলেও বিভিন্ন পরিস্থিতি মনে রেখে ডিজাইন করা হয়েছিল।
জুমুলেটর

5
@ জুমুলেটর: যদি আপনার পুনরুক্তিকারীকে অনুলিপি করা একটি পারফরম্যান্স উদ্বেগ হয় তবে আপনার মোকাবেলা করতে আরও বড় সমস্যা রয়েছে।
মাকিং হাঁস

8

অথবা আপনি ব্যবহার করতে পারেন std::advance

vector<int>::iterator i = L.begin();
advance(i, 2);

-3

বাস্তবে std :: ভেক্টর বোঝানো হয় যখন প্রয়োজন হয় তখন সি ট্যাব হিসাবে ব্যবহৃত হয়। (সি ++ স্ট্যান্ডার্ড অনুরোধ করে যে ভেক্টর বাস্তবায়নের জন্য, যতদূর আমি জানি - উইকিপিডিয়ায় অ্যারের প্রতিস্থাপন ) উদাহরণস্বরূপ, আমার মতে এই ফলোভিং করা পুরোপুরি আইনী:

int main()
{

void foo(const char *);

sdt::vector<char> vec;
vec.push_back('h');
vec.push_back('e');
vec.push_back('l');
vec.push_back('l');
vec.push_back('o');
vec.push_back('/0');

foo(&vec[0]);
}

অবশ্যই, foo অবশ্যই প্যারামিটার হিসাবে প্রদত্ত ঠিকানাটি অনুলিপি করে কোথাও এটি সংরক্ষণ করবে না, বা আপনার প্রোগ্রামে নিশ্চিত হওয়া উচিত যে কোনও নতুন আইটেমকে ভিস্কে কখনও ঠেলে না দেওয়া বা তার ক্ষমতা পরিবর্তন করার অনুরোধ করা উচিত। বা ঝুঁকি বিভাজন ত্রুটি ...

সুতরাং আপনার উদাহরণে এটি বাড়ে

vector.insert(pos, &vec[first_index], &vec[last_index]);

তারা আমাকে কেবল পয়েন্টার হলে পুনরাবৃত্তির কাছে কেন বিমূর্ত করার সিদ্ধান্ত নিয়েছে তা আমাকে অবাক করে তোলে ... তারা মূলত এই ক্ষমতাগুলি "লুকিয়ে" রাখছেন।
এমপেন

একত্রীকরণের জন্য? যেহেতু এটি আপনাকে আপনার কোডে অন্য কোনও ধরণের ধারক হিসাবে খুব সহজেই ভেক্টর উদাহরণ সরাতে দেয়।
yves বাউমেস 21 '45

4
& ভিসি [i] একটি পয়েন্টার দেয় যা ভেক্টর <> :: পুনরুক্তকারীর সাথে প্রয়োজনীয়ভাবে সামঞ্জস্য নয়। vec.begin () + আপনার লাইব্রেরি এটির যেকোন পুনরুক্তিকারী হওয়ার উপকারিতা রয়েছে - উদাহরণস্বরূপ, ডিবাগ মোডে চেক করা পুনরাবৃত্তিগুলি সহ। সুতরাং, যদি আপনার কোনও পয়েন্টার প্রয়োজন না হয় (উদাহরণস্বরূপ I / O এর জন্য), আপনার সর্বদা পুনরাবৃত্তিকে পছন্দ করা উচিত।
বিক্রয়বিটজে

@ কেরেকএসবি সি ++ স্ট্যান্ডার্ড ড্রাফটে ২৩.৩..6.১ থেকে: "একটি ভেক্টরের উপাদানগুলি স্বচ্ছভাবে সংরক্ষণ করা হয়, যার অর্থ যদি ভি একটি ভেক্টর <টি, বরাদ্দকারী> যেখানে টি বুল ব্যতীত অন্য ধরণের, তবে এটি পরিচয় & v [ n] == & ভি [0] + n সমস্ত 0 <= n <v.size () "
yves বাউমস

2
@ আইভেসবাউমস: ভেক্টর ইটারেটরগুলির সাথে এর কোনও যোগসূত্র নেই। যাইহোক, এটা সত্যি যে নগ্ন পয়েন্টার হয় এছাড়াও iterators - তারা শুধু নও ভেক্টর iterators।
কেরেক এসবি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.