আমি বিশ্বাস করি আপনার সঠিক পর্যবেক্ষণ আছে তবে ভুল ব্যাখ্যা!
কপিটি মানটি ফেরত দিয়ে আসবে না, কারণ প্রতিটি সাধারণ চালাক সংকলক (N) আরভিও এই ক্ষেত্রে ব্যবহার করবে । সি ++ 17 থেকে এটি বাধ্যতামূলক, সুতরাং আপনি ফাংশন থেকে স্থানীয় উত্পন্ন ভেক্টরকে ফিরিয়ে কোনও অনুলিপি দেখতে পাবেন না।
ঠিক আছে, আসুন std::vector
এবং এটি নির্মাণের সময় বা ধাপে ধাপে পূরণ করে কী হবে তা নিয়ে কিছুটা খেলি lets
প্রথমত, এমন একটি ডেটা টাইপ তৈরি করা যাক যা প্রতিটি অনুলিপি তৈরি করে বা এর মতো দৃশ্যমান হয়:
template <typename DATA >
struct VisibleCopy
{
private:
DATA data;
public:
VisibleCopy( const DATA& data_ ): data{ data_ }
{
std::cout << "Construct " << data << std::endl;
}
VisibleCopy( const VisibleCopy& other ): data{ other.data }
{
std::cout << "Copy " << data << std::endl;
}
VisibleCopy( VisibleCopy&& other ) noexcept : data{ std::move(other.data) }
{
std::cout << "Move " << data << std::endl;
}
VisibleCopy& operator=( const VisibleCopy& other )
{
data = other.data;
std::cout << "copy assign " << data << std::endl;
}
VisibleCopy& operator=( VisibleCopy&& other ) noexcept
{
data = std::move( other.data );
std::cout << "move assign " << data << std::endl;
}
DATA Get() const { return data; }
};
এবং এখন কিছু পরীক্ষা-নিরীক্ষা শুরু করা যাক:
using T = std::vector< VisibleCopy<int> >;
T Get1()
{
std::cout << "Start init" << std::endl;
std::vector< VisibleCopy<int> > vec{ 1,2,3,4 };
std::cout << "End init" << std::endl;
return vec;
}
T Get2()
{
std::cout << "Start init" << std::endl;
std::vector< VisibleCopy<int> > vec(4,0);
std::cout << "End init" << std::endl;
return vec;
}
T Get3()
{
std::cout << "Start init" << std::endl;
std::vector< VisibleCopy<int> > vec;
vec.emplace_back(1);
vec.emplace_back(2);
vec.emplace_back(3);
vec.emplace_back(4);
std::cout << "End init" << std::endl;
return vec;
}
T Get4()
{
std::cout << "Start init" << std::endl;
std::vector< VisibleCopy<int> > vec;
vec.reserve(4);
vec.emplace_back(1);
vec.emplace_back(2);
vec.emplace_back(3);
vec.emplace_back(4);
std::cout << "End init" << std::endl;
return vec;
}
int main()
{
auto vec1 = Get1();
auto vec2 = Get2();
auto vec3 = Get3();
auto vec4 = Get4();
// All data as expected? Lets check:
for ( auto& el: vec1 ) { std::cout << el.Get() << std::endl; }
for ( auto& el: vec2 ) { std::cout << el.Get() << std::endl; }
for ( auto& el: vec3 ) { std::cout << el.Get() << std::endl; }
for ( auto& el: vec4 ) { std::cout << el.Get() << std::endl; }
}
আমরা কী পর্যবেক্ষণ করতে পারি:
উদাহরণ 1) আমরা একটি প্রাথমিককরণ তালিকা থেকে একটি ভেক্টর তৈরি করি এবং সম্ভবত আমরা আশা করি যে আমরা 4 বার নির্মাণ এবং 4 পদক্ষেপগুলি দেখতে পাব। তবে আমরা 4 কপি পাই! এটি কিছুটা রহস্যজনক মনে হচ্ছে, তবে কারণটি প্রাথমিকের তালিকার বাস্তবায়ন! কেবল তালিকা থেকে সরানোর অনুমতি নেই কারণ তালিকা থেকে পুনরাবৃত্তি এমন একটি const T*
যা এটি থেকে উপাদান সরিয়ে নেওয়া অসম্ভব করে তোলে। এই বিষয়ের একটি বিশদ উত্তর এখানে পাওয়া যাবে: ইনিশিয়ালাইজার_লিস্ট এবং পদার্থবিদ্যার স্থানান্তর
উদাহরণ 2) এই ক্ষেত্রে, আমরা একটি প্রাথমিক নির্মাণ এবং মানটির 4 কপি পাই। এটি বিশেষ কিছু নয় এবং আমরা প্রত্যাশাও করতে পারি।
উদাহরণ 3) এছাড়াও এখানে, আমরা নির্মাণ এবং আশানুরূপ কিছু পদক্ষেপগুলি। আমার স্টিল প্রয়োগের সাথে ভেক্টর প্রতিবার 2 গুণক দ্বারা বৃদ্ধি পায়। সুতরাং আমরা একটি প্রথম নির্মাণ দেখতে পাচ্ছি, অন্যটি এবং ভেক্টরটি 1 থেকে 2 পর্যন্ত আকার পরিবর্তন করায় আমরা প্রথম উপাদানটির পদক্ষেপ দেখতে পাই। 3 টি যুক্ত করার সময়, আমরা 2 থেকে 4 এর আকার পরিবর্তন করতে দেখি যার জন্য প্রথম দুটি উপাদানগুলির সরানো দরকার needs আশানুরূপ সব!
উদাহরণ 4) এখন আমরা স্থান সংরক্ষণ করি এবং পরে পূরণ করব। এখন আমাদের আর কোনও অনুলিপি নেই এবং কোনও পদক্ষেপ নেই!
সব ক্ষেত্রেই, আমরা ভ্যাক্টরকে একেবারেই কলারে ফেরত দিয়ে কোনও পদক্ষেপ বা অনুলিপি দেখতে পাই না! (এন) আরভিও চলছে এবং এই পদক্ষেপে আর কোনও পদক্ষেপের প্রয়োজন নেই!
আপনার প্রশ্নে ফিরে:
"সি ++ প্রফুল্ল অনুলিপি অপারেশনগুলি কীভাবে সন্ধান করবেন"
উপরের মত দেখা গেছে, আপনি ডিবাগিংয়ের উদ্দেশ্যে একটি প্রক্সি ক্লাস চালু করতে পারেন।
অনুলিপি-বেসরকারীকে ব্যক্তিগত করা অনেক ক্ষেত্রে কার্যকর নাও হতে পারে, কারণ আপনার কাছে কিছু চাওয়া অনুলিপি এবং কিছু লুকানো রয়েছে। উপরে হিসাবে, উদাহরণস্বরূপ 4 কোডটি কোনও ব্যক্তিগত অনুলিপি-কর্টারের সাথে কাজ করবে! এবং আমি প্রশ্নের উত্তর দিতে পারি না, উদাহরণ 4 যদি দ্রুততম হয় তবে আমরা শান্তিতে শান্তি পূরণ করি।
দুঃখিত যে আমি এখানে "অযাচিত" অনুলিপিগুলির সন্ধানের জন্য সাধারণ সমাধানের প্রস্তাব দিতে পারি না। এমনকি যদি আপনি কল করার জন্য আপনার কোডটি খনন করেন তবে আপনি memcpy
সমস্ত কিছুই খুঁজে পাবেন না তবে এটি memcpy
অপ্টিমাইজ করা হবে এবং আপনি সরাসরি আপনার লাইব্রেরি memcpy
ফাংশনে কোনও কল ছাড়াই কাজটি করছেন এমন কিছু এসেম্বলারের নির্দেশাবলী দেখতে পাবেন ।
আমার ইঙ্গিতটি এমন একটি ছোটখাটো সমস্যার দিকে মনোনিবেশ করা নয়। আপনার যদি সত্যিকারের পারফরম্যান্সের সমস্যা থাকে তবে একজন প্রোফাইলার নিন এবং মাপুন। অনেক সম্ভাব্য পারফরম্যান্স হত্যাকারী রয়েছে, যে উত্সাহযুক্ত memcpy
ব্যবহারের জন্য বেশি সময় বিনিয়োগ করা তেমন উপযুক্ত ধারণা বলে মনে হয় না।
std::vector
করা উচিত নয়, এটির উদ্দেশ্যটি কী । আপনার উদাহরণটি একটি স্পষ্ট অনুলিপি দেখায়, এবং এটি কেবল প্রাকৃতিক এবং সঠিক পদ্ধতির (আবার ইমো)std::move
ফাংশনটি প্রয়োগ করা যেমন আপনি নিজের মতামত জানান তবে কোনও অনুলিপি আপনি চান তা যদি না থাকে। নোট করুন যে কয়েকটি সংকলক অপ্টিমাইজেশন পতাকাগুলি চালু করা থাকলে এবং ভেক্টরটি অপরিবর্তিত থাকলে অনুলিপিটি বাদ দিতে পারে।