স্ট্যান্ড :: চাল () কী এবং এটি কখন ব্যবহার করা উচিত?


655
  1. এটা কি?
  2. এটার কাজ কি?
  3. এটি কখন ব্যবহার করা উচিত?

ভাল লিঙ্ক প্রশংসা করা হয়।




12
এই প্রশ্ন উল্লেখ করা হয় std::move(T && t); std::move(InputIt first, InputIt last, OutputIt d_first)সম্পর্কিত একটি অ্যালগরিদম যা একটি উপস্থিত আছে std::copy। আমি এটি উল্লেখ করছি যাতে অন্যরা যতটা বিভ্রান্ত না হয় ততক্ষণ আমি যখন প্রথম std::moveতিনটি যুক্তি নিয়ে মুখোমুখি হয়েছিলাম was en.cppreferences.com/w/cpp/algorithm/move
josaphatv

উত্তর:


285

সি ++ 11 এর জন্য উইকিপিডিয়া পৃষ্ঠা আর-মান উল্লেখ এবং সরানো কনস্ট্রাক্টর

  1. সি ++ ১১-এ, অনুলিপি নির্মাণকারী ছাড়াও, অবজেক্টে মুভ কনস্ট্রাক্টর থাকতে পারে।
    (এবং অ্যাসাইনমেন্ট অপারেটরদের অনুলিপি করা ছাড়াও, তাদের কাছে সরানো অ্যাসাইনমেন্ট অপারেটর রয়েছে))
  2. মুভি কনস্ট্রাক্টরটি অনুলিপি নির্মাণকারীর পরিবর্তে ব্যবহৃত হয়, যদি বস্তুর "রাল্যু-রেফারেন্স" ( Type &&) থাকে।
  3. std::move() এটি এমন একটি castালাই যা এটির থেকে চলতে সক্ষম করার জন্য কোনও বস্তুর একটি মূল্য-রেফারেন্স তৈরি করে।

অনুলিপিগুলি এড়ানোর এটি একটি নতুন সি ++ উপায়। উদাহরণস্বরূপ, একটি মুভ কনস্ট্রাক্টর ব্যবহার করে, একটি std::vectorকেবলমাত্র তার অভ্যন্তরীণ পয়েন্টারটিকে নতুন অবজেক্টে ডেটাতে অনুলিপি করতে পারে, সরানো অবজেক্টটিকে রাষ্ট্র থেকে সরানো অবস্থায় রেখে দেয়, সুতরাং সমস্ত ডেটা অনুলিপি করে না। এটি সি ++ - বৈধ হবে।

চলা শব্দার্থবিজ্ঞান, মূল্যায়ন, নিখুঁত ফরোয়ার্ডিংয়ের জন্য গুগলিং চেষ্টা করুন Try


39
সরানো-শব্দার্থবিজ্ঞানের জন্য সরানো বস্তুটি বৈধ থাকার প্রয়োজন , যা কোনও ভুল রাষ্ট্র নয়। (যুক্তিযুক্ত: এটি এখনও ধ্বংস করতে হবে, এটি কাজ করতে হবে।)
GManNGG

13
@ জিএমান: ঠিক আছে, এটি এমন একটি রাজ্যে থাকতে হবে যা ধ্বংস করতে নিরাপদ, তবে, আফাইক, এটি অন্য কোনও কিছুর জন্য ব্যবহারযোগ্য হতে হবে না।
ঝ্যান লিংস

8
@ জ্যানলিনেক্স: ঠিক আছে। নোট করুন যে স্ট্যান্ডার্ড লাইব্রেরিতে অতিরিক্তভাবে সরানো অবজেক্টগুলি নিয়োগযোগ্য হতে হবে, তবে এটি কেবল স্টাডলাইবে ব্যবহৃত সামগ্রীর জন্য, সাধারণ প্রয়োজন নয়।
GManNickG

24
-1 "স্টাডি :: মুভ () হ'ল সরু শব্দার্থিক শব্দ ব্যবহারের সি ++ 11 উপায়" দয়া করে এটি ঠিক করুন। std::move()মুভ শব্দার্থক ব্যবহারের উপায় নয়, মুভ শব্দার্থক প্রোগ্রামারটিতে স্বচ্ছভাবে সঞ্চালিত হয়। moveএটির একমাত্র বিন্দু থেকে অন্য একটি বিন্দুতে মূল্য প্রেরণের যেখানে lালিউডটি আর ব্যবহৃত হবে না।
Manu343726

15
আমি আরও যেতে হবে। std::moveনিজেই "কিছুই না" করে - এর শূন্য পার্শ্ব প্রতিক্রিয়া রয়েছে। এটি কেবলমাত্র সংকলককে সংকেত দেয় যে প্রোগ্রামার সেই পাত্তা দেয় না যে সেই বস্তুর আর কী ঘটে। অর্থাৎ এটি সফ্টওয়্যারটির অন্য অংশগুলিকে অবজেক্ট থেকে সরানোর অনুমতি দেয় তবে এটি সরানোর প্রয়োজন হয় না। প্রকৃতপক্ষে, কোনও মূল্যের রেফারেন্সের প্রাপক এটি ডেটা দিয়ে কী করবে বা করবে না সে সম্পর্কে কোনও প্রতিশ্রুতি দেওয়ার দরকার নেই।
অ্যারন ম্যাকডেইড

240

1. "এটি কি?"

std::move() প্রযুক্তিগতভাবে একটি ফাংশন থাকাকালীন - আমি বলব এটি আসলে কোনও ফাংশন নয় । এটি সংকলক যেভাবে অভিব্যক্তির মান বিবেচনা করে তার মধ্যে একটি ধরণের রূপান্তরকারী

২. "এটি কী করে?"

প্রথম বিষয় লক্ষণীয় যে std::move() আসলে কিছুই সরানো হয় না । এটি একটি মূল্যকে (যেমন একটি নামযুক্ত ভেরিয়েবল) হওয়া থেকে এক্সভালিউতে রূপান্তরিত করে । একটি xvalue সংকলকটি বলে:

আপনি আমাকে লুণ্ঠন করতে পারেন, আমি যে কোনও কিছু ধরে রেখেছি তা স্থানান্তর করতে এবং অন্য কোথাও এটি ব্যবহার করতে পারেন (যেহেতু যেভাবেই আমি শীঘ্রই ধ্বংস হয়ে যাব) "।

অন্য কথায়, যখন আপনি ব্যবহার std::move(x), আপনি cannibalize করতে কম্পাইলার, যার ফলে করছি x। সুতরাং, যদি xবলি, মেমরিতে এটির নিজস্ব বাফার - std::move()সংকলকটি লেখার পরে এর পরিবর্তে অন্য কোনও বস্তুর নিজস্ব থাকতে পারে।

আপনি কোনও মূল্য থেকেও সরে যেতে পারেন (যেমন আপনি অস্থায়ী হয়ে যাচ্ছেন) তবে এটি খুব কমই কার্যকর।

৩. "এটি কখন ব্যবহার করা উচিত?"

এই প্রশ্নটি জিজ্ঞাসা করার অন্য একটি উপায় হ'ল আমি কোন বিদ্যমান অবজেক্টের সংস্থানগুলির জন্য নরমাংসকরণ করব? " ভাল, আপনি যদি অ্যাপ্লিকেশন কোডটি লিখছেন তবে আপনি সম্ভবত সংকলক দ্বারা তৈরি অস্থায়ী বস্তুগুলির সাথে খুব বেশি গোলমাল করবেন না। সুতরাং প্রধানত আপনি এটি কন্সট্রাক্টর, অপারেটর পদ্ধতি, স্ট্যান্ডার্ড-লাইব্রেরি-অ্যালগোরিদম-এর মতো ফাংশন ইত্যাদিতে করতে পারেন যেখানে বস্তুগুলি স্বয়ংক্রিয়ভাবে অনেকগুলি তৈরি এবং ধ্বংস হয়ে যায়। অবশ্যই এটি থাম্বের একটি নিয়ম মাত্র।

একটি সাধারণ ব্যবহার অনুলিপি করার পরিবর্তে একটি বস্তু থেকে অন্য বস্তুর কাছে 'চলন্ত' সংস্থান। @ গুইলিউম এই পৃষ্ঠায় লিঙ্কগুলি রয়েছে যার সরল সংক্ষিপ্ত উদাহরণ রয়েছে: কম অনুলিপি সহ দুটি বস্তু অদলবদল করা।

template <class T>
swap(T& a, T& b) {
    T tmp(a);   // we now have two copies of a
    a = b;      // we now have two copies of b (+ discarded a copy of a)
    b = tmp;    // we now have two copies of tmp (+ discarded a copy of b)
}

সরানো ব্যবহারের সাহায্যে আপনার চারপাশে অনুলিপি করার পরিবর্তে সংস্থানগুলি অদলবদল করতে দেয়:

template <class T>
swap(T& a, T& b) {
    T tmp(std::move(a));
    a = std::move(b);   
    b = std::move(tmp);
}

এন, সাইজের এন Tবলার পরে কী হয় তা ভাবুন vector<int>। প্রথম সংস্করণে আপনি 3 * এন উপাদানগুলি পড়েন এবং লিখেন, দ্বিতীয় সংস্করণে আপনি মূলত ভেক্টর বাফারগুলিতে 3 টি বাটন, এবং 3 বাফার আকারগুলি পড়েন এবং লিখেন। অবশ্যই, ক্লাসটি Tচলন্ত কীভাবে করতে হবে তা জানতে হবে; আপনার ক্লাসে Tকাজ করার জন্য ক্লাসের জন্য একটি মুভ-এসাইনমেন্ট অপারেটর এবং একটি মুভ-কনস্ট্রাক্টর থাকা উচিত ।


3
দীর্ঘ সময় ধরে আমি এই সরানো শব্দার্থক শব্দগুলির কথা শুনেছি, আমি কখনই সেগুলিতে সন্ধান করিনি। এই বিবরণটি থেকে আপনি এটিকে কেবল একটি গভীর অনুলিপি না করে অগভীর অনুলিপি বলে মনে হচ্ছে।
জেব্রাফিশ

7
@ টিটোনমারিস: এটি অনুলিপি ব্যতীত - মূল মানটি আর ব্যবহারযোগ্য নয়।
einpoklum

3
@ জেব্রাফিশ আপনি আরও ভুল হতে পারবেন না অগভীর অনুলিপিটি মূলটিকে একই অবস্থায় ফেলে দেয়, একটি চালচলনের ফলে সাধারণত আসলটি খালি হয় বা অন্যথায় বৈধ অবস্থায় থাকে।
রুবেনবিবি

16
@ রুবেনভ জেব্রা সম্পূর্ণ ভুল নয়। যদিও এটি সত্য যে বিভ্রান্তিকর ত্রুটিগুলি এড়াতে মূল ক্যানিবিলাইজড অবজেক্টটি সাধারণত ইচ্ছাকৃতভাবে নাশকতা করা হয় (উদাহরণস্বরূপ, এটি পয়েন্টটির মালিক নয় বলে সিগন্যাল করতে তার পয়েন্টারগুলি সেট করুন), সত্য যে সরল থেকে একটি পয়েন্টার অনুলিপি করে পুরো পদক্ষেপটি বাস্তবায়িত হয়েছিল গন্তব্যে (এবং ইচ্ছাকৃতভাবে পয়েন্টটির সাথে কিছু করা এড়ানো) আসলে অগভীর অনুলিপিটির স্মরণ করিয়ে দেয়। আসলে, আমি এতদূর যেতে হবে যেমন বলতে চাই যে একটি পদক্ষেপ হল অগভীর কপি, উৎস একটি আংশিক নিজে থেকেই নষ্ট দ্বারা ঐচ্ছিকরূপে অনুসরণ করে। (অবিরত)
অরবিট

3
(অবিরত) যদি আমরা এই সংজ্ঞাটি অনুমোদন করি (এবং আমি এটি পছন্দ করি) তবে @ জেব্রাফিশের পর্যবেক্ষণটি ভুল নয়, কিছুটা অসম্পূর্ণ।
অরবিট

145

আপনি যখন কোনও অনুলিপি না করেই অন্য কোনও সামগ্রীর বিষয়বস্তু "স্থানান্তর" করতে চান তখন আপনি সরানো ব্যবহার করতে পারেন (যেমন সামগ্রীটি অনুলিপি করা হয় না, এজন্য এটি অনন্য_পিটারের মতো কিছু অনুলিপিযোগ্য বস্তুগুলিতে ব্যবহার করা যেতে পারে)। কোনও স্ট্যান্ডার্ড :: পদক্ষেপের সাথে কোনও অবজেক্টের জন্য অনুলিপি (এবং প্রচুর সময় সাশ্রয়) না করে অস্থায়ী সামগ্রীর সামগ্রী নেওয়াও সম্ভব।

এই লিঙ্কটি আমাকে সত্যই সাহায্য করেছে:

http://thbecker.net/articles/rvalue_references/section_01.html

আমার উত্তরটি যদি খুব দেরিতে আসে তবে আমি দুঃখিত, তবে আমি এইচটিডি :: পদক্ষেপের জন্য একটি ভাল লিঙ্কের সন্ধানও করছিলাম এবং আমি লিঙ্কগুলি কিছুটা "আষ্টেয়ার" এর উপরে পেয়েছি।

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


26
ভাল লিঙ্ক। আমি সর্বদা উইকিপিডিয়া নিবন্ধ এবং অন্যান্য লিঙ্কগুলি খুঁজে পেয়েছিলাম যা আমি বিভ্রান্তিকর হয়ে পড়েছিলাম কারণ তারা কেবল আপনার দিকে সত্য ঘটনা ফেলে দেয় এবং প্রকৃত অর্থ / যুক্তিটি কী তা বোঝার জন্য এটি আপনার কাছে রেখে দেয়। কনস্ট্রাক্টরটিতে "মুভ সেমেন্টিকস" বরং স্পষ্টতই, চারপাশে && - এর মানগুলি সম্পর্কে যাবতীয় বিবরণগুলি নয় ... সুতরাং টিউটোরিয়াল-শৈলীর বর্ণনাটি খুব সুন্দর ছিল।
খ্রিস্টান স্টিবার

66

প্রশ্ন: কী std::move?

উত্তর: std::move()মূল্যের রেফারেন্সে কাস্ট করার জন্য সি ++ স্ট্যান্ডার্ড লাইব্রেরি থেকে একটি ফাংশন।

সরলভাবে std::move(t)সমান:

static_cast<T&&>(t);

একটি মূল্যবোধ এমন একটি অস্থায়ী যা এটি সংজ্ঞায়িত অভিব্যক্তির বাইরে স্থির থাকে না, যেমন একটি মধ্যবর্তী ফাংশন ফলাফল যা কখনও কোনও ভেরিয়েবলের মধ্যে সঞ্চয় হয় না।

int a = 3; // 3 is a rvalue, does not exist after expression is evaluated
int b = a; // a is a lvalue, keeps existing after expression is evaluated

স্ট্যান্ড :: মুভ () এর একটি বাস্তবায়ন N2027 এ দেওয়া হয়েছে : "মূল্য সংক্ষেপের সংক্ষিপ্ত পরিচিতি" নিম্নরূপ:

template <class T>
typename remove_reference<T>::type&&
std::move(T&& a)
{
    return a;
}

যেমন আপনি দেখতে পাচ্ছেন, মান ( ), রেফারেন্স প্রকার ( ) বা মূল্যসূত্র রেফারেন্স ( ) দিয়ে ডাকা হলেও তা std::moveফেরত দেয় T&&না ।TT&T&&

প্রশ্ন: এটি কি করে?

উত্তর: castালাই হিসাবে এটি রানটাইমের সময় কিছু করে না। সংকলককে বলা কেবলমাত্র প্রাসঙ্গিক যে আপনি রেফাল্য হিসাবে রেফারেন্সটি বিবেচনা করে চালিয়ে যেতে চান।

foo(3 * 5); // obviously, you are calling foo with a temporary (rvalue)

int a = 3 * 5;
foo(a);     // how to tell the compiler to treat `a` as an rvalue?
foo(std::move(a)); // will call `foo(int&& a)` rather than `foo(int a)` or `foo(int& a)`

এটি কি করে না :

  • যুক্তিটির একটি অনুলিপি তৈরি করুন
  • অনুলিপি নির্মাণকারীকে কল করুন
  • আর্গুমেন্ট অবজেক্ট পরিবর্তন করুন

প্রশ্ন: এটি কখন ব্যবহার করা উচিত?

উত্তর: আপনি std::moveযদি এমন ফাংশনগুলিতে কল করতে চান যা কোনও যুক্তি যা অকার্যকর (অস্থায়ী এক্সপ্রেশন) নয় এমন পদার্থকে মুভমেন্ট শব্দকে সমর্থন করে।

এটি আমার জন্য নিম্নলিখিত ফলো-আপ প্রশ্নগুলি ভোগ করে:

  • পদক্ষেপ শব্দার্থক কি? শব্দার্থবিজ্ঞানের অনুলিপি শব্দার্থবিজ্ঞানের বিপরীতে মুভমেন্ট একটি প্রোগ্রামিং কৌশল যা কোনও অবজেক্টের সদস্যরা অন্য অবজেক্টের সদস্যদের অনুলিপি না করে 'দখল' গ্রহণের মাধ্যমে আরম্ভ করা হয়। এই ধরনের 'টেক ওভার' পয়েন্টার এবং রিসোর্স হ্যান্ডলগুলি দিয়ে কেবল বোঝায়, যা অন্তর্নিহিত ডেটার পরিবর্তে পয়েন্টার বা পূর্ণসংখ্যার হ্যান্ডেল অনুলিপি করে সস্তায় স্থানান্তরিত হতে পারে।

  • কোন ধরণের ক্লাস এবং অবজেক্টস মুভ সিমানটিককে সমর্থন করে? এটি আপনার বিকাশকারী হিসাবে আপনার নিজের ক্লাসে মুভ শব্দার্থক প্রয়োগ করা যদি তাদের সদস্যদের অনুলিপি না করে তাদের সদস্যদের স্থানান্তর করে উপকৃত হয় তবে এটি আপনার উপর নির্ভর করে। আপনি মুভ শব্দার্থক প্রয়োগ করার পরে, আপনি সরাসরি অনেক লাইব্রেরি প্রোগ্রামারদের কাজ থেকে উপকৃত হবেন যারা দক্ষতার সাথে মুভ শব্দার্থক সহ ক্লাস পরিচালনা করার জন্য সমর্থন যোগ করেছেন।

  • সংকলকটি কেন এটি নিজের মতো করে বের করতে পারে না? সংকলক কেবল কোনও ফাংশনের অন্য ওভারলোডকে কল করতে পারে না যদি আপনি না বলে থাকেন। আপনাকে অবশ্যই সংকলকটিকে ফাংশনের নিয়মিত বা সরানো সংস্করণটি কল করা উচিত কিনা তা চয়ন করতে সহায়তা করতে হবে।

  • কোন পরিস্থিতিতে আমি সংস্থাপককে বলতে চাই যে এটি একটি পরিবর্তনশীলকে মূল হিসাবে বিবেচনা করবে? এটি সম্ভবত টেমপ্লেট বা লাইব্রেরি ফাংশনে ঘটবে, যেখানে আপনি জানেন যে একটি মধ্যবর্তী ফলাফল উদ্ধার হতে পারে।


2
মন্তব্যে শব্দার্থক সহ কোড উদাহরণের জন্য বড় +1। অন্যান্য শীর্ষ উত্তরগুলি std সংজ্ঞায়িত করে: "চাল" নিজেই ব্যবহার করে সরানো - আসলে কিছুই স্পষ্ট করে না! --- আমি বিশ্বাস করি এটি উল্লেখ করার মতো যে আর্গুমেন্টের অনুলিপি না করার অর্থ আসল মানটি নির্ভরযোগ্যভাবে ব্যবহার করা যায় না।
ty

34

স্ট্যান্ড :: নিজেই সরানো সত্যিই খুব বেশি কিছু করে না। আমি ভেবেছিলাম যে এটি একটি অবজেক্টের জন্য মুভিড কনস্ট্রাক্টর নামে পরিচিত, তবে এটি সত্যই কেবল একটি টাইপ কাস্ট সম্পাদন করে (একটি মানকে একটি লভালিউ ভেরিয়েবল castালাই যাতে বলা যায় যে চলকটি পরিবর্তনকারী বা অ্যাসাইনমেন্ট অপারেটরের একটি আর্গুমেন্ট হিসাবে পাস করতে পারে)।

সুতরাং std :: সরানো কেবল পদক্ষেপ শব্দার্থ ব্যবহারের পূর্বসূর হিসাবে ব্যবহৃত হয়। অস্থায়ী বস্তুগুলির সাথে কাজ করার জন্য মুভ সেমেন্টিকগুলি মূলত একটি কার্যকর উপায়।

অবজেক্ট বিবেচনা করুন A = B + C + D + E + F;

এটি দুর্দান্ত দেখাচ্ছে কোড, তবে E + F একটি অস্থায়ী বস্তু উত্পাদন করে। তারপরে ডি + টেম্প আরেকটি অস্থায়ী অবজেক্ট তৈরি করে। শ্রেণীর প্রতিটি সাধারণ "+" অপারেটরে, গভীর অনুলিপিগুলি ঘটে।

উদাহরণ স্বরূপ

Object Object::operator+ (const Object& rhs) {
    Object temp (*this);
    // logic for adding
    return temp;
}

এই ফাংশনে অস্থায়ী অবজেক্টের সৃষ্টি অকেজো - এই অস্থায়ী বস্তুগুলি যেভাবেই সুযোগের বাইরে চলে যাওয়ার সাথে সাথে লাইনের শেষে মুছে ফেলা হবে।

আমরা বরং সাময়িক বস্তুগুলি "লুণ্ঠন" করতে অস্থায়ী বস্তুগুলি ব্যবহার করতে পারি এবং এর মতো কিছু করতে পারি

 Object& Object::operator+ (Object&& rhs) {
     // logic to modify rhs directly
     return rhs;
 }

এটি অনাবশ্যক গভীর কপি তৈরি করা এড়ানো উচিত। উদাহরণের রেফারেন্সের সাথে, গভীর কপি করার একমাত্র অংশটি এখন E + F rest বাকী স্থানান্তর শব্দার্থক শব্দ ব্যবহার করে। মুভি কনস্ট্রাক্টর বা অ্যাসাইনমেন্ট অপারেটরকে ফল এ-তে নির্ধারণের জন্যও প্রয়োগ করা দরকার


3
আপনি সরানো শব্দার্থবিজ্ঞানের কথা বলেছেন। আপনার উত্তরে আপনার যুক্ত করা উচিত যে স্ট্যান্ড :: পদক্ষেপটি কীভাবে ব্যবহার করা যেতে পারে কারণ প্রশ্নটি তার সম্পর্কে জিজ্ঞাসা করে।
কুশিক শেঠি

2
@ কুশিক স্টাড :: পদক্ষেপটি তেমন কিছু করতে পারে না - তবে সরানো শব্দার্থক প্রয়োগে ব্যবহৃত হয়। আপনি যদি
স্টাড

1
"বেশি কিছু করতে পারে না" (হ্যাঁ একটি মূল রেফারেন্সের জন্য একটি স্ট্যাটিক_কাস্ট)। আসলে এটি কী করে এবং ওয়াই এটি করে যা ওপি বলেছিল। আপনাকে কীভাবে std :: সরানো কাজ করে তা জানার দরকার নেই তবে আপনি কী শিথিল শব্দার্থক কাজগুলি তা জানতে পেরেছেন। তদ্ব্যতীত, "তবে সরানো শব্দার্থকগুলি প্রয়োগ করতে ব্যবহৃত হয়" এর অন্যদিকে এটি। চলন্ত শব্দার্থবিজ্ঞান জানুন এবং আপনি স্টাডি :: বুঝতে পারবেন অন্যথায় না। সরানো কেবল চলাচলে সহায়তা করে এবং নিজেই পদক্ষেপের শব্দার্থ ব্যবহার করে। std :: সরানো তার যুক্তিটিকে যথাযথ রেফারেন্সে রূপান্তরিত করা ব্যতীত আর কিছুই করে না, যা পদক্ষেপ পদার্থবিদ্যার প্রয়োজন।
কুশিক শেঠি

10
"তবে ই + এফ একটি অস্থায়ী বস্তু উত্পাদন করে" - অপারেটর +বাম থেকে ডানদিকে যায়, ডান থেকে বামে যায় না। সুতরাং B+Cপ্রথম হবে!
অজয়

8

"এটা কি?" এবং "এটি কি করে?" উপরে ব্যাখ্যা করা হয়েছে।

"এটি কখন ব্যবহার করা উচিত" এর একটি উদাহরণ দেব

উদাহরণস্বরূপ, আমাদের মধ্যে এটির বড় অ্যারের মতো প্রচুর সংস্থান সহ একটি বর্গ রয়েছে।

class ResHeavy{ //  ResHeavy means heavy resource
    public:
        ResHeavy(int len=10):_upInt(new int[len]),_len(len){
            cout<<"default ctor"<<endl;
        }

        ResHeavy(const ResHeavy& rhs):_upInt(new int[rhs._len]),_len(rhs._len){
            cout<<"copy ctor"<<endl;
        }

        ResHeavy& operator=(const ResHeavy& rhs){
            _upInt.reset(new int[rhs._len]);
            _len = rhs._len;
            cout<<"operator= ctor"<<endl;
        }

        ResHeavy(ResHeavy&& rhs){
            _upInt = std::move(rhs._upInt);
            _len = rhs._len;
            rhs._len = 0;
            cout<<"move ctor"<<endl;
        }

    // check array valid
    bool is_up_valid(){
        return _upInt != nullptr;
    }

    private:
        std::unique_ptr<int[]> _upInt; // heavy array resource
        int _len; // length of int array
};

পরীক্ষার কোড:

void test_std_move2(){
    ResHeavy rh; // only one int[]
    // operator rh

    // after some operator of rh, it becomes no-use
    // transform it to other object
    ResHeavy rh2 = std::move(rh); // rh becomes invalid

    // show rh, rh2 it valid
    if(rh.is_up_valid())
        cout<<"rh valid"<<endl;
    else
        cout<<"rh invalid"<<endl;

    if(rh2.is_up_valid())
        cout<<"rh2 valid"<<endl;
    else
        cout<<"rh2 invalid"<<endl;

    // new ResHeavy object, created by copy ctor
    ResHeavy rh3(rh2);  // two copy of int[]

    if(rh3.is_up_valid())
        cout<<"rh3 valid"<<endl;
    else
        cout<<"rh3 invalid"<<endl;
}

নীচে হিসাবে আউটপুট:

default ctor
move ctor
rh invalid
rh2 valid
copy ctor
rh3 valid

আমরা দেখতে পারেন std::moveসঙ্গে move constructorতোলে সহজে রিসোর্স রুপান্তর।

আর কোথায় std::moveদরকারী?

std::moveউপাদানগুলির একটি অ্যারে বাছাই করার সময়ও দরকারী হতে পারে। অনেকগুলি বাছাই করা অ্যালগরিদম (যেমন নির্বাচনের বাছাই এবং বুদ্বুদ সাজান) জোড়াগুলির উপাদানগুলি অদলবদল করে কাজ করে। পূর্বে, অদলবদল করতে আমাদের কপি-শব্দার্থবিজ্ঞান অবলম্বন করতে হয়েছিল। এখন আমরা মুভ শব্দার্থক ব্যবহার করতে পারি, যা আরও কার্যকর।

আমরা যদি একটি স্মার্ট পয়েন্টার দ্বারা পরিচালিত সামগ্রীগুলি অন্যটিতে স্থানান্তর করতে চাই তবে এটি কার্যকরও হতে পারে।

উদ্ধৃত:


0

একটি (সাধারণ) কাস্টম ভেক্টরের জন্য std :: সরানো ব্যবহার করে একটি পূর্ণ উদাহরণ এখানে দেওয়া হয়েছে

প্রত্যাশিত আউটপুট:

 c: [10][11]
 copy ctor called
 copy of c: [10][11]
 move ctor called
 moved c: [10][11]

হিসাবে সংকলন:

  g++ -std=c++2a -O2 -Wall -pedantic foo.cpp

কোড:

#include <iostream>
#include <algorithm>

template<class T> class MyVector {
private:
    T *data;
    size_t maxlen;
    size_t currlen;
public:
    MyVector<T> () : data (nullptr), maxlen(0), currlen(0) { }
    MyVector<T> (int maxlen) : data (new T [maxlen]), maxlen(maxlen), currlen(0) { }

    MyVector<T> (const MyVector& o) {
        std::cout << "copy ctor called" << std::endl;
        data = new T [o.maxlen];
        maxlen = o.maxlen;
        currlen = o.currlen;
        std::copy(o.data, o.data + o.maxlen, data);
    }

    MyVector<T> (const MyVector<T>&& o) {
        std::cout << "move ctor called" << std::endl;
        data = o.data;
        maxlen = o.maxlen;
        currlen = o.currlen;
    }

    void push_back (const T& i) {
        if (currlen >= maxlen) {
            maxlen *= 2;
            auto newdata = new T [maxlen];
            std::copy(data, data + currlen, newdata);
            if (data) {
                delete[] data;
            }
            data = newdata;
        }
        data[currlen++] = i;
    }

    friend std::ostream& operator<<(std::ostream &os, const MyVector<T>& o) {
        auto s = o.data;
        auto e = o.data + o.currlen;;
        while (s < e) {
            os << "[" << *s << "]";
            s++;
        }
        return os;
    }
};

int main() {
    auto c = new MyVector<int>(1);
    c->push_back(10);
    c->push_back(11);
    std::cout << "c: " << *c << std::endl;
    auto d = *c;
    std::cout << "copy of c: " << d << std::endl;
    auto e = std::move(*c);
    delete c;
    std::cout << "moved c: " << e << std::endl;
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.