একটি ভেক্টর অন্যতে অনুলিপি করার দ্রুত উপায়


155

আমি দুটি উপায় পছন্দ করি:

void copyVecFast(const vec<int>& original)
{
  vector<int> newVec;
  newVec.reserve(original.size());
  copy(original.begin(),original.end(),back_inserter(newVec));
}

void copyVecFast(vec<int>& original)
{

  vector<int> newVec;
  newVec.swap(original); 
}

তুমি এটা কিভাবে কর?


14
দ্বিতীয়টির বিভ্রান্তকারী নাম রয়েছে - কারণ এটি অনুলিপি নয় (যদিও এটি দ্রুত)।
বেনামে

উত্তর:


126

আপনার দ্বিতীয় উদাহরণটি কার্যকর হয় না যদি আপনি রেফারেন্স দ্বারা যুক্তি পাঠান। আপনি কি বলতে চেয়েছিলেন?

void copyVecFast(vec<int> original) // no reference
{

  vector<int> new_;
  new_.swap(original); 
}

এটি কাজ করবে, তবে একটি সহজ উপায়

vector<int> new_(original);

ভাল, এটি কাজ করে। তবে এটি কোনও ভেক্টরগুলির জন্য কাজ করছে না: উদাহরণস্বরূপ: ভেক্টর <int> এ [এন];
ABCDexter

8
এটি স্বপ, অনুলিপি নয়।
এসডি

1
@ এসডিডি - না তা নয়। যুক্তি তালিকা পরীক্ষা করুন। originalফাংশন আর্গুমেন্টের একটি অনুলিপি।
rlbond

249

তারা যদিও একই নয়, তাই না? একটি হ'ল একটি অনুলিপি, অন্যটি একটি অদলবদল । সুতরাং ফাংশন নাম।

আমার প্রিয়টি হ'ল:

a = b;

কোথায় aএবং bভেক্টর।


3
প্রকৃতপক্ষে পদ্ধতির মান দিয়ে চলেছে, সংকলকটি অনুলিপি নির্মাণকারীকে কল করে এবং তারপরে নতুন তৈরি হওয়া উপাদানটিকে অদলবদল করে। এই কারণেই rlbond একই প্রভাব অর্জনের জন্য সরাসরি অনুলিপি নির্মাণকারীকে কল করার পরামর্শ দেয়।
ডেভিড রদ্রিগেজ - ড্রিবিস

1
যাইহোক, আপনি কোনও ফাংশন ছাড়াই rlbon কল করতে পারবেন না যা আসলটি ভ্যাল হিসাবে পাস করে। অন্যথায়, আসলটি খালি হবে। দ্বিতীয় সমাধানটি নিশ্চিত করে দিয়েছে যে আপনি সর্বদা মান দ্বারা কল করবেন এবং তাই আপনি আসল ভেক্টরের তারিখটি হারাবেন না। (অদলবদল পয়েন্টারের সাথে চুক্তি করে)
ইয়াদ ইব্রাহিম

এটি কি খ এর উপাদানগুলিকে একটিতে নিয়ে যাবে না (b = আকারের সাথে ছেড়ে যাবে)?
জোনাথন

1
@Jonathan। ধরে নিচ্ছি আপনি a = bতখন কোন কথা বলছেন না। অ্যাসাইনমেন্টের অর্থ: পরিবর্তন না করে aসমান করুন । বিপরীতে তাদের বিষয়বস্তু বিনিময় হবে (তাই এর এখন হবে যাই হোক না কেন এর আগে ছিল)। আপনি সম্ভবত কোনও মুভ অপারেশনের কথা ভাবছেন (যেমনটি সি ++ 11 তে ঘটে থাকে, তবে এর মতো কোনও সাধারণ কার্যালয়ে নেই)। এই ধরনের একটি পদক্ষেপ ছেড়ে দিতেন একটি ইন, হুম, "আকর্ষণীয়" অবস্থায় - দেখুন stackoverflow.com/questions/17730689/...bbstd::swap(a, b)bsizeab
ড্যানিয়েল Earwicker

1
@Jonathan। ডাবল অ্যাম্পারস্যান্ড নোট করুন &&। এই সংস্করণটি কেবলমাত্র মূল্যবোধের রেফারেন্সের জন্য ব্যবহৃত হবে। এটি কোনও নিরপেক্ষ মানের সাথে মেলে না (যেমন bআমার উপরের উদাহরণে) example এমনকি আরও বৃহত্তর স্তরের জটিলতার জন্য en.cppreferences.com/w/cpp/language/value_category দেখুন bকরে a = std::move(b);আপনি একটিতে পরিণত হতে পারেন ।
ড্যানিয়েল আর্উইকার

74

এটি কোনও ভেক্টরের অনুলিপি তৈরি করার অন্য একটি বৈধ উপায়, কেবল এটির নির্মাণকারী ব্যবহার করুন:

std::vector<int> newvector(oldvector);

এটি std::copyসম্পূর্ণ ভেক্টরটিকে std::back_insertনতুন ভেক্টরে শেষ করতে শুরু করার জন্য হাঁটা ব্যবহারের চেয়ে আরও সহজ ।

বলা হচ্ছে, আপনার .swap()একটি অনুলিপি নয়, পরিবর্তে এটি দুটি ভেক্টরকে অদলবদল করে। আপনি আর কিছু না রাখার জন্য আসলটি সংশোধন করবেন! কোনটি অনুলিপি নয়।


19

সরাসরি উত্তর:

  • =অপারেটর ব্যবহার করুন

আমরা পাবলিক সদস্য ফাংশন ব্যবহার করতে পারেন std::vector::operator=পাত্রের std::vectorঅন্য একটি ভেক্টর থেকে মানগুলি নির্ধারণের জন্য।

  • কনস্ট্রাক্টর ফাংশন ব্যবহার করুন

তদ্ব্যতীত, একটি কন্সট্রাক্টর ফাংশনটিও বোধগম্য হয়। প্যারামিটার হিসাবে অন্য ভেক্টরের সাথে একটি কনস্ট্রাক্টর ফাংশন (উদাঃ x) xএকই ক্রমে প্রতিটি উপাদানগুলির একটি অনুলিপি সহ একটি ধারক তৈরি করে ।

সতর্ক করা:

  • ব্যবহার করবেন না std::vector::swap

std::vector::swapঅন্য কোনও ভেক্টরকে অনুলিপি করছে না , এটি প্রকৃতপক্ষে দুটি ভেক্টরের উপাদানগুলি অদলবদল করছে, এর নাম অনুসারে। অন্য কথায়, উত্স ভেক্টর থেকে অনুলিপি করার পরে সংশোধন করা std::vector::swapহয়, যা সম্ভবত আপনি প্রত্যাশিত হন না।

  • গভীর বা অগভীর কপি?

উত্স ভেক্টরের উপাদানগুলি যদি অন্য ডেটারে পয়েন্টার হয় তবে কখনও কখনও একটি গভীর অনুলিপি চাওয়া হয়।

উইকিপিডিয়া অনুসারে:

একটি গভীর অনুলিপি, যার অর্থ ক্ষেত্রগুলি বিন্যস্ত করা হয়েছে: অনুলিপি করা অবজেক্টগুলির রেফারেন্সের পরিবর্তে কোনও রেফারেন্সযুক্ত বস্তুর জন্য নতুন অনুলিপি অবজেক্ট তৈরি করা হয়েছে, এবং এইগুলিতে বি স্থাপন করা হয়েছে to

আসলে, ডিপ অনুলিপি করার জন্য বর্তমানে সি ++ তে কোনও অন্তর্নির্মিত উপায় নেই। উপরে উল্লিখিত সমস্ত উপায় অগভীর। যদি একটি গভীর অনুলিপি প্রয়োজন হয়, আপনি কোনও ভেক্টরকে অতিক্রম করতে পারেন এবং ম্যানুয়ালি উল্লেখগুলির অনুলিপি তৈরি করতে পারেন। বিকল্পভাবে, একটি পুনরুক্তি ট্রভারিংয়ের জন্য বিবেচনা করা যেতে পারে। পুনরুক্তিকারী সম্পর্কে আলোচনা এই প্রশ্নের বাইরে beyond

তথ্যসূত্র

std::vectorসিপি্লুপ্লাস.কম এর পৃষ্ঠা


14

ভেক্টরদের অনুলিপি করার জন্য আপনার অদলবদল ব্যবহার করা উচিত নয়, এটি "আসল" ভেক্টরকে বদলে দেবে।

পরিবর্তে নতুনটিতে প্যারামিটার হিসাবে মূলটি পাস করুন।


14
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2

-14

যদি ভেক্টর ইতিমধ্যে উপস্থিত থাকে এবং আপনি কেবল অনুলিপি করতে চান, আপনি এটি করতে পারেন:

newVec.resize(oldVec.size());
memcpy(&newVec.at(0), &oldVec.at(0), oldVec.size());

1
দয়া করে স্মরণ করিয়ে দেবেন না এছাড়াও এটি কাজ করবে না কারণ মেমকিপি বাইটগুলিতে আকার নেয়। এছাড়াও যদি অন্য ভেক্টর ইতিমধ্যে বিদ্যমান থাকে তবে আপনি কেবল এটি করতে পারেন newVec = oldVecযা অন্য উত্তরগুলির মতো।
এফডিনফ

হ্যাঁ তুমিই ঠিক. আমি তা দেখিনি। @ এফডিনফ, যদিও এটি একের নীচে কাজ করে তবে আপনি মেমকি ব্যবহার না করার পরামর্শ দিচ্ছেন কেন? এটিকে নতুনভেদ = ওল্ডেকের থেকে অনেক দ্রুত বলে মনে হচ্ছে। memcpy (& newVec.at (0), এবং OldVec.at (0), oldVec.size () * সাইজের (int));
শেগড

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

আমি আপনার সমালোচনা করছিলাম না .. আমার দলের নেতৃত্বও একই পরামর্শ দিয়েছে এবং আমি বোঝার চেষ্টা করছি।
sgowd

(আমি ভাবিনি যে আপনি আমার সমালোচনা করছেন।) এখনও এমন কিছু আছে যা আপনি বুঝতে পারছেন না?
এফডিনফ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.