ভেক্টর :: পুনরায় আকার () এবং ভেক্টর :: রিজার্ভ () এর মধ্যে পছন্দ


151

আমি আমার vectorসদস্য ভেরিয়েবলের জন্য কিছু মেমরি প্রাক বরাদ্দ করছি । নীচের কোডটি ন্যূনতম অংশ

class A {
  vector<string> t_Names;
public:
  A () : t_Names(1000) {}
};

এখন কিছু সময়, t_Names.size()সমান হলে 1000। আমি আকারটি বাড়িয়ে তুলতে চাইছি 100। তারপরে যদি এটি পৌঁছায় তবে 1100আবার আরও বাড়িয়ে নিন 100

আমার প্রশ্ন হ'ল vector::resize()এবং এর মধ্যে কোনটি বেছে নেবেন vector::reserve()। এই জাতীয় দৃশ্যে এর চেয়ে ভাল আর কোনও পছন্দ আছে কি?

সম্পাদনা করুন : এর জন্য আমার ধরণের নির্ভুল অনুমান রয়েছে t_Names। আমি এটা কাছাকাছি হতে অনুমান 700করতে 800। তবে নির্দিষ্ট (কদাচিৎ) পরিস্থিতিতে এটি আরও বেশি বাড়তে পারে 1000


34
আপনি বুঝতে পেরেছেন যে এটির অর্থ হ'ল ভেক্টর বৃদ্ধিটি আর ধ্রুবক সময়কে ধীরে ধীরে ধীরে ধীরে চালিত করা হয় না এবং আপনি ব্যবহারের পারফরম্যান্স সুবিধাগুলির মধ্যে একটি হারাবেন std::vector
ব্লাস্টফর্নেস

1
সম্পর্কিত, সি ++ আরও সহজতর করা দেখুন: ডক ডবস সাইটে ভেক্টরগুলি কীভাবে বৃদ্ধি পায়।
jwww

উত্তর:


262

দুটি ফাংশনই বিভিন্ন কাজ করে!

resize()পদ্ধতি (এবং কন্সট্রাকটর আর্গুমেন্ট প্রাপ্ত করতে পার যে সমতূল্য) ঢোকান বা ভেক্টর করার উপাদানের ডিলিট উপযুক্ত সংখ্যা এটি দেওয়া আকার করতে (এটা তাদের মূল্য নির্দিষ্ট করতে ঐচ্ছিক দ্বিতীয় যুক্তি আছে)। এটি প্রভাব ফেলবে size(), পুনরাবৃত্তি সমস্ত উপাদানগুলির উপর দিয়ে যাবে, পুশ_ব্যাক তাদের পরে sertোকানো হবে এবং আপনি সরাসরি এটি ব্যবহার করে অ্যাক্সেস করতে পারবেন operator[]

reserve()পদ্ধতি ওনলি মেমোরি বরাদ্দ, কিন্তু পাতার এটা uninitialized। এটি কেবল প্রভাবিত করে capacity()তবে size()অপরিবর্তিত থাকবে। বস্তুর জন্য কোনও মূল্য নেই, কারণ ভেক্টরে কোনও কিছুই যুক্ত হয় না। এরপরে আপনি যদি উপাদানগুলিকে সন্নিবেশ করেন তবে কোনও পুনরায় স্থান ঘটবে না, কারণ এটি আগে থেকেই করা হয়েছিল, তবে এটিই কেবল কার্যকর।

সুতরাং এটি আপনি যা চান তার উপর নির্ভর করে। আপনি যদি 1000 ডিফল্ট আইটেমের অ্যারে চান তবে ব্যবহার করুন resize()। আপনি যদি এমন একটি অ্যারে চান যেখানে আপনি 1000 টি আইটেম সন্নিবেশ করানোর আশা করছেন এবং কয়েকটি বরাদ্দ এড়াতে চান তবে ব্যবহার করুন reserve()

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

সম্পাদনা 2: বিজ্ঞাপন প্রশ্ন সম্পাদনা: আপনার যদি প্রাথমিক অনুমান থাকে তবে reserve()সেই অনুমান। যদি এটি পর্যাপ্ত পরিমাণে পরিণত হয় না, তবে কেবল ভেক্টরকে এটি করতে দিন।


আমি প্রশ্নটি সম্পাদনা করেছি। আমি জন্য নির্দিষ্ট অনুমান আছে vector
iammilind

3
@ জ্যান: ভাল, এটি প্রয়োজনীয় সম্পত্তি রক্ষণাবেক্ষণের পক্ষে আপনি নিজের পক্ষে কতটা কঠিন হয়ে গেছেন তা অনুসারে এটি ভঙ্গুর বা নয়। x.reserve(x.size() + newdata); vector<int>::iterator special_element = get_special_element(x); for (int i = 0; i < newdata; ++i) { if some_function(i, special_element) x.push_back(i); }জায়গা সংরক্ষণের মতোই কিছু শক্তিশালী is আসলে কতগুলি উপাদান যুক্ত হবে তা আমার কোনও ধারণা নেই তবে আমার উপরের আবদ্ধ আছে। অবশ্যই সন্দেহ যখন, ভেক্টরগুলির সাথে আপনি কেবল পুনরাবৃত্তির পরিবর্তে সূচকগুলি ব্যবহার করতে পারেন, পার্থক্যটি সাধারণত নগণ্য।
স্টিভ জেসোপ

4
আপনার শব্দটি ইতিমধ্যে সঠিক উত্তর সম্পর্কে সচেতন কাউকে বোঝায়, তবে সহজেই প্রশ্ন জিজ্ঞাসার প্রয়োজন এমন লোককে বিভ্রান্ত করতে পারে। "আকার পরিবর্তন () ... ভেক্টরকে প্রদত্ত সংখ্যক উপাদান সন্নিবেশ করিয়ে দেবে" - এটি প্রথমবার ব্যবহারের সময় সত্য - এটি সাধারণত অনুরোধ করা নম্বর এবং প্রাক-বিদ্যমানের মধ্যে পার্থক্য সন্নিবেশ করে size()। "রিজার্ভ () পদ্ধতিটি কেবল মেমরি বরাদ্দ করে" - এটি capacity()ইতিমধ্যে পর্যাপ্ত কিনা তার উপর নির্ভর করে মেমরির বরাদ্দ বা নাও করতে পারে , এটি উপাদানগুলিকে সরিয়ে নিয়ে তাদের মূল স্মৃতিশক্তি হ্রাস করতেও পারে। "কয়েকটি বরাদ্দ এড়াতে চান" এবং অনুলিপিগুলি
টনি ডেলরয়

19
আসলে, ধাক্কা দেওয়ার আগে সংরক্ষণ করা জরুরী এবং অবশ্যই ব্যবহার করা উচিত। ধরে নিন যে আপনি কোনও রকম 3 ডি মডেল লোডার কোডিং করছেন এবং মডেলটির 15000 টির মতো শীর্ষবিন্দু রয়েছে। আপনি যদি পূর্বের বরাদ্দ না দিয়ে লোড করার সময় প্রতিটি শীর্ষবিন্দুটিকে ধাক্কা দেওয়ার চেষ্টা করেন তবে এটি গুরুতর সময় নেবে। আমি ব্যক্তিগতভাবে এটি অনুভব করেছি, আমি প্রায় 100000 উল্লম্ব সহ একটি গাড়ি .obj মডেলটি লোড করার চেষ্টা করেছি, এটি 30 সেকেন্ড সময় নিয়েছিল। তারপরে আমি .reserve () দিয়ে প্রাক-বরাদ্দ ব্যবহার করে কোডটি রিফ্যাক্ট করেছিলাম, এখন এটি 3 সেকেন্ড সময় নেয়। কোডের শুরুতে কেবল একটি .re সংরক্ষণ (100000) লাগানো 27 সেকেন্ডে সঞ্চয় করা হয়েছে।
deniz

1
@ এডিনিজ এটি ১০০০০০ স্কেলে তুচ্ছ সত্য, তবে ১০০-৩০০ স্কেলে খুব একটা সত্য নয়, যেখানে অকারণে সংরক্ষণ করা যদি অপব্যয় করা যায়।
'20

30

resize()কেবল মেমরি বরাদ্দ করে না, এটি পছন্দসই আকারের মতো অনেকগুলি উদাহরণ তৈরি করে যা আপনি যুক্তি হিসাবে পাস করেন। তবে কেবল মেমরি বরাদ্দ করে, এটি উদাহরণ তৈরি করে না। এটাই,resize()reserve()

std::vector<int> v1;
v1.resize(1000); //allocation + instance creation
cout <<(v1.size() == 1000)<< endl;   //prints 1
cout <<(v1.capacity()==1000)<< endl; //prints 1

std::vector<int> v2;
v2.reserve(1000); //only allocation
cout <<(v2.size() == 1000)<< endl;   //prints 0
cout <<(v2.capacity()==1000)<< endl; //prints 1

আউটপুট ( অনলাইন ডেমো ):

1
1
0
1

আপনি resize()পছন্দসই নাও হতে পারেন, যদি আপনি ডিফল্ট-তৈরি বস্তু না চান। এটি পাশাপাশি ধীর হবে। এছাড়াও, আপনি যদি এতে push_back()নতুন উপাদান তৈরি করেন তবে নতুন মেমরি বরাদ্দsize() করে ভেক্টরটির আরও বৃদ্ধি হবে (যার অর্থ বিদ্যমান উপাদানগুলিকে সদ্য বরাদ্দ হওয়া মেমরি স্পেসে সরিয়ে নেওয়া)। আপনি যদি ইতিমধ্যে পর্যাপ্ত বরাদ্দ মেমরির বিষয়টি নিশ্চিত করার জন্য শুরুতে ব্যবহার করে থাকেন তবে ভেক্টর যখন আপনার কাছে আসবে তখন বাড়বে , তবে এটির জন্য আপনার সংরক্ষিত স্থানটি শেষ না হওয়া পর্যন্ত এটি নতুন মেমরির পুনরায় বরাদ্দ করবে নাreserve()size()push_back()


6
করার পরে reserve(N), আমরা operator []নিরীহভাবে ব্যবহার করতে পারি । সঠিক?
iammilind

2
সবচেয়ে বাস্তবায়নের সঠিক পরিমাণ আপনি অনুরোধ বরাদ্দ হবে যদিও reserve, স্পেসিফিকেশন শুধুমাত্র প্রয়োজন এটা বরাদ্দ অন্তত অনেক, তাই কিছু বাস্তবায়নের কিছু সীমানাতে ধরপাকড় করতে পারে যে এবং এইভাবে 1000. বেশী ধারণক্ষমতা দেন
জানুয়ারী Hudec

16
@ আইয়ামিলিন্ড: না, সূচকটি বৃহত্তর বা সমান হলে v.size()। নোট করুন যে ভেক্টর reserve(N)পরিবর্তন হয় না size()
নওয়াজ

5
@ আইয়ামিলিন্ড: ভুল রিসার্ভে কল করার পরে, কোনও এন্ট্রি যুক্ত করা হয় না, কেবল তাদের যুক্ত করার জন্য পর্যাপ্ত মেমরি পাওয়া যায়।
জান হুডেক

2

আপনার বিবরণ থেকে, দেখে মনে হচ্ছে আপনি ভেক্টর টি_নামের বরাদ্দকৃত স্টোরেজ স্পেসটি "সংরক্ষণ" করতে চান।

নোট করুন যে resizeসদ্য বরাদ্দ ভেক্টর যেখানে প্রাথমিক reserveবরাদ্দ কিন্তু নির্মাণ করে না। সুতরাং, 'রিজার্ভ' 'পুনরায় আকার দেওয়ার' চেয়ে অনেক দ্রুত

আপনি পুনরায় আকার এবং রিজার্ভের পার্থক্য সম্পর্কিত ডকুমেন্টেশনগুলিকে উল্লেখ করতে পারেন


1
: তার জন্যে এখানে পড়ুন দয়া করে ভেক্টর এবং ধারণক্ষমতা ( কেন? )
sehe

1
লিঙ্কটি সংযোজনের জন্য ধন্যবাদ, সেহে
ডুব দিন

2

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

এই জাতীয় দৃশ্যে এর চেয়ে ভাল আর কোনও পছন্দ আছে কি?

এটি পূর্বনির্ধারিত আচরণের বিরুদ্ধে লড়াই করার সময় আপনার লক্ষ্যগুলির উপর নির্ভর করে। কিছু লোক কাস্টমাইজড বরাদ্দকারীদের পক্ষে যাবে - তবে আপনাকে ভালভাবে পরামর্শ দেওয়ার জন্য আপনার প্রোগ্রামটিতে আপনি কী সমাধান করার চেষ্টা করছেন তা আমাদের সত্যই একটি ভাল ধারণা দরকার।

তদ্ব্যতীত, অনেক ভেক্টর বাস্তবায়ন বরাদ্দকৃত উপাদানগুলির সংখ্যা কেবল দ্বিগুণ হবে যখন তারা বাড়বে - আপনি কি পিক বরাদ্দের মাপকে ন্যূনতম করার চেষ্টা করছেন বা আপনি কোনও লক ফ্রি প্রোগ্রাম বা অন্য কোনও কিছুর জন্য পর্যাপ্ত জায়গা সংরক্ষণ করার চেষ্টা করছেন?


" আপনি যখন সংরক্ষণ করতে চাইবেন না যখন বস্তুগুলি আরম্ভ করা উচিত। সংরক্ষণ করুন " "সঠিক সূত্রটি যখন আপনি চান না যে অবজেক্টের অস্তিত্ব থাকতে পারে । এটি একটি তুচ্ছ গঠনমূলক ধরণের অবিচ্ছিন্ন অ্যারের মতো নয়, যেখানে বস্তুগুলি পড়া যায় না তবে নির্ধারিত হতে পারে; বরং কেবলমাত্র স্মৃতি সংরক্ষিত থাকে তবে এতে কোনও বস্তুর অস্তিত্ব থাকে না, তাই এগুলি ব্যবহার করে operator[]বা কিছু ব্যবহার করা যায় না ।
আন্ডারস্কোর_ডে
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.