টি + অ্যান্ড (ডাবল অ্যাম্পারস্যান্ড) সি ++ 11 এর অর্থ কী?


799

আমি সি ++ 11 এর কয়েকটি নতুন বৈশিষ্ট্য খতিয়ে দেখছি এবং এর মধ্যে একটি আমি লক্ষ্য করেছি যে ভেরিয়েবলগুলি ঘোষণা করার ক্ষেত্রে ডাবল এম্পারস্যান্ড T&& var

শুরু করার জন্য, এই জন্তুটিকে কী বলা হয়? আমি আশা করি গুগল আমাদের বিরামচিহ্ন অনুসন্ধান করার অনুমতি দেয়।

এর অর্থ কী?

প্রথম নজরে, এটি একটি দ্বৈত রেফারেন্স হিসাবে দেখা যাচ্ছে (সি-স্টাইলের ডাবল পয়েন্টারগুলির মতো T** var), তবে আমি এটির জন্য ব্যবহারের ক্ষেত্রে ভাবতে খুব কষ্ট পাচ্ছি।


55
আমি এটি সি ++ - এফএএকে যুক্ত করেছি, যেহেতু আমি নিশ্চিত ভবিষ্যতে এটি আরও সামনে আসবে।
GManNickG


41
আপনি গুগল ব্যবহার করে এটি অনুসন্ধান করতে পারেন, আপনার কেবল বাক্যাংশটি উদ্ধৃতিতে আবদ্ধ করতে হবে : google.com/#q="T%26%26 "এখন আপনার প্রথম প্রশ্ন হিসাবে প্রশ্ন রয়েছে। :)
sbi

এখানে একটি অনুরূপ প্রশ্নের খুব ভাল, সহজেই বোঝার প্রতিক্রিয়া রয়েছে stackoverflow.com/questions/7153991/…
ড্যানিয়েল

2
গুগলে "সি ++ দুটি অ্যাম্পারস্যান্ড প্যারামিটার" অনুসন্ধান করার জন্য আমি তিনটি স্ট্যাকওভারফ্লো প্রশ্ন পেয়েছি এবং আপনার প্রথমটি ছিল। সুতরাং আপনি যদি "দুটি অ্যাম্পারস্যান্ডস প্যারামিটার" বানান করতে পারেন তবে এর জন্য আপনার বিরামচিহ্নগুলিও ব্যবহার করার দরকার নেই।
সার্জিওল

উত্তর:


668

এটি একটি মূল রেফারেন্স ঘোষণা করে (মান প্রস্তাব নথি) proposal

মূল্যবোধের রেফারেন্সগুলির একটি ভূমিকা এখানে ।

মাইক্রোসফ্টের স্ট্যান্ডার্ড লাইব্রেরি বিকাশকারীদের একজনের যথাযথ রেফারেন্সগুলিতে এক গভীরভাবে গভীর চেহারা ।

সতর্কতা: এমএসডিএন সম্পর্কিত লিঙ্কিত নিবন্ধ ("মূল্যায়ন রেফারেন্স: ভিসি 10-তে সি ++ 0x বৈশিষ্ট্যসমূহ, পার্ট 2") মূল্যবোধের রেফারেন্সগুলির একটি খুব সুস্পষ্ট পরিচয়, তবে সি ++ 11 খসড়ার ক্ষেত্রে সত্য যে রেভেলু রেফারেন্সগুলি ছিল তা সম্পর্কে বিবৃতি দেয় makes মান, কিন্তু চূড়ান্ত এক জন্য সত্য নয়! বিশেষত, এটি বিভিন্ন পয়েন্টে বলেছে যে মূল্যের রেফারেন্সগুলি লভ্যুয়ালের সাথে আবদ্ধ হতে পারে, যা একসময় সত্য ছিল তবে পরিবর্তিত হয়েছিল eg (উদাহরণস্বরূপ int x; int && rrx = x; আর জিসিসিতে আর সংকলন করা হয় না) - জুলাই 13 '14 এ 16 ডিসেম্বর

একটি C ++ 03 রেফারেন্সের মধ্যে সর্বাধিক পার্থক্য (বর্তমানে সি ++ 11-এ একটি ল্যাভেলু রেফারেন্স বলা হয়) এটি কনস্টের হওয়া ছাড়াই অস্থায়ীর মতো কোনও মূল্যকে আবদ্ধ করতে পারে। সুতরাং, এই বাক্য গঠনটি এখন আইনী:

T&& r = T();

মূলসূত্র উল্লেখগুলি নিম্নলিখিতগুলির জন্য প্রাথমিকভাবে সরবরাহ করে:

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

উদাহরণস্বরূপ, একটি অনুলিপি নির্মাণকারী দেখতে দেখতে এটি দেখতে পাবেন:

foo(foo const& other)
{
    this->length = other.length;
    this->ptr = new int[other.length];
    copy(other.ptr, other.ptr + other.length, this->ptr);
}

যদি এই কনস্ট্রাক্টরকে অস্থায়ীভাবে পাস করা হয়, তবে অনুলিপিটি অপ্রয়োজনীয় হবে কারণ আমরা জানি অস্থায়ী মাত্র ধ্বংস হয়ে যাবে; ইতিমধ্যে বরাদ্দ থাকা সংস্থাগুলি কেন ব্যবহার করবেন না? সি ++ তে, অনুলিপি প্রতিরোধের কোনও উপায় নেই কারণ আমরা নির্ধারণ করতে পারি না যে আমরা অস্থায়ী হয়েছি। সি ++ 11 এ আমরা একটি মুভ কনস্ট্রাক্টরকে ওভারলোড করতে পারি:

foo(foo&& other)
{
   this->length = other.length;
   this->ptr = other.ptr;
   other.length = 0;
   other.ptr = nullptr;
}

এখানে বড় পার্থক্য লক্ষ্য করুন: মুভ কনস্ট্রাক্টর তার যুক্তিটি সংশোধন করে। এটি কার্যকরভাবে তৈরি করা অবজেক্টটিতে অস্থায়ীভাবে "সরানো" হবে, যার ফলে অপ্রয়োজনীয় অনুলিপি দূর হবে।

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

foo f1((foo())); // Move a temporary into f1; temporary becomes "empty"
foo f2 = std::move(f1); // Move f1 into f2; f1 is now "empty"

পারফেক্ট ফরওয়ার্ডিং । মূল্যসূচক উল্লেখগুলি টেম্পলেটড ফাংশনগুলির জন্য যুক্তিগুলি যথাযথভাবে ফরোয়ার্ড করতে দেয়। উদাহরণস্বরূপ এই কারখানার কার্যকারিতাটি ধরুন:

template <typename T, typename A1>
std::unique_ptr<T> factory(A1& a1)
{
    return std::unique_ptr<T>(new T(a1));
}

যদি আমরা ডাকা হয় factory<foo>(5), আর্গুমেন্টটি অনুমান করা হবে int&, যা কোনও আক্ষরিক 5 এর সাথে আবদ্ধ হবে না, এমনকি যদি fooতার নির্মাণকারী একটি নেয় int। ঠিক আছে, আমরা পরিবর্তে ব্যবহার করতে পারি A1 const&, তবে কি যদি fooকনস্ট্রাক্টর নন-কনস্ট্যান্ট রেফারেন্স দ্বারা যুক্তিটি গ্রহণ করা হয়? সত্যিকারের জেনেরিক কারখানা ফাংশন করতে, আমরা ফ্যাক্টরি জমিদার করতে হবে A1&এবং এর A1 const&। কারখানাটি যদি 1 টি প্যারামিটারের ধরণ নেয় তবে এটি সূক্ষ্ম হতে পারে, তবে প্রতিটি অতিরিক্ত পরামিতি টাইপ 2 দ্বারা প্রয়োজনীয় ওভারলোড সেটটি গুণ করে। এটি খুব তাড়াতাড়ি কল্পনাযোগ্য নয়।

মান সংক্রান্ত রেফারেন্সগুলি স্ট্যান্ডার্ড লাইব্রেরিটিকে কোনও std::forwardফাংশন সংজ্ঞায়িত করার অনুমতি দেয় যা সঠিকভাবে ল্যাভালু / রেভ্যালু রেফারেন্সগুলি ফরোয়ার্ড করতে পারে। কীভাবে std::forwardকাজ করে সে সম্পর্কে আরও তথ্যের জন্য , এই দুর্দান্ত উত্তরটি দেখুন

এটি আমাদের মত কারখানার কার্যকারিতা সংজ্ঞায়িত করতে সক্ষম করে:

template <typename T, typename A1>
std::unique_ptr<T> factory(A1&& a1)
{
    return std::unique_ptr<T>(new T(std::forward<A1>(a1)));
}

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

যখন ফাংশন প্যারামিটার প্রকার ফর্ম হল T&&যেখানে Tএকটি টেমপ্লেট প্যারামিটার হয়, এবং ফাংশন যুক্তি প্রকারের একটি lvalue হয় A, টাইপ A&টেমপ্লেট যুক্তি সিদ্ধান্তগ্রহণ জন্য ব্যবহৃত হয়।

সুতরাং, আমরা যেমন কারখানা ব্যবহার করতে পারেন:

auto p1 = factory<foo>(foo()); // calls foo(foo&&)
auto p2 = factory<foo>(*p1);   // calls foo(foo const&)

গুরুত্বপূর্ণ মূল্যসূচক রেফারেন্স বৈশিষ্ট্য :

  • ওভারলোড রেজোলিউশনের জন্য, ল্যাভেলুগুলি লভ্যালু রেফারেন্সগুলিকে বাধ্যতামূলক পছন্দ করে এবং মূল্যগুলি রেভ্যালু রেফারেন্সের সাথে বাধ্যতামূলক পছন্দ করে । সুতরাং টেম্পোরারিগুলি কেন একটি অনুলিপি নির্মাণকারী / অ্যাসাইনমেন্ট অপারেটরের উপর একটি মুভ কনস্ট্রাক্টর / মুভ এসাইনমেন্ট অপারেটরকে অনুরোধ করতে পছন্দ করে।
  • মূলসূত্র উল্লেখগুলি অন্তর্নিহিত রূপান্তরগুলির ফলস্বরূপ মূল্যবোধ এবং অস্থায়ী সংস্থাগুলির সাথে আবদ্ধ হবে । অর্থাত্ float f = 0f; int&& i = f;সুগঠিত হয় কারণ ভাসাটি নিখুঁতভাবে ইন-তে রূপান্তরিত হয়; রেফারেন্সটি একটি অস্থায়ী সম্পর্কে হবে যা রূপান্তরটির ফলাফল।
  • নামযুক্ত মূল্যসূত্র উল্লেখগুলি হ'ল মূল্য। নামবিহীন মূল্যসূচক উল্লেখগুলি হল মূল্যবোধ val কেন std::moveকলটি প্রয়োজনীয় তা বুঝতে এটি গুরুত্বপূর্ণ :foo&& r = foo(); foo f = std::move(r);

65
+1 এর জন্য Named rvalue references are lvalues. Unnamed rvalue references are rvalues.; এটি না জেনেই আমি বুঝতে চেষ্টা করেছি কেন লোকেরা T &&t; std::move(t);দীর্ঘ সময় ধরে সরানো সেক্টরগুলিতে এবং এই জাতীয় কাজগুলিতে একটি কাজ করে।
কিংবদন্তি 2 কে

@ ম্যাক্সিমইগুরুশকিন: সেই উদাহরণে, আর একটি খাঁটি মূল্য (সাময়িক) এর সাথে আবদ্ধ হয় এবং তাই অস্থায়ীটির তার আজীবন সুযোগ বাড়ানো উচিত, না?
পিটার হুয়েন

@ পিটারহুইন আমি এটিকে পিছনে নিচ্ছি, একটি আর-মান উল্লেখটি একটি অস্থায়ী জীবনকালকে বাড়িয়ে তোলে।
ম্যাক্সিম এগারুশকিন

32
সতর্কতা বিশেষ : দুটিই MSDN ( "Rvalue তথ্যসূত্র: সি ++ 0x VC10, পার্ট 2 বৈশিষ্ট্য") উপর লিঙ্ক নিবন্ধ হয় Rvalue রেফারেন্স করার জন্য একটি খুব পরিষ্কার ভূমিকা, কিন্তু যে ছিল Rvalue রেফারেন্স সম্পর্কে বিবৃতি তোলে একবার সত্য খসড়া সি ++ 11 মান, কিন্তু চূড়ান্ত এক জন্য সত্য নয় ! বিশেষত, এটি বিভিন্ন পয়েন্টে বলেছে যে মূল্যের রেফারেন্সগুলি লভ্যুয়ালের সাথে আবদ্ধ হতে পারে, যা একসময় সত্য ছিল , তবে পরিবর্তিত হয়েছিল eg (উদাঃ int x; int &&rrx = x;
জিসিসিতে

@ পিটারহুইন উপরের উদাহরণে, typename identity<T>::type& aসমান নয় T&?
আইবিপি 73

81

এটি একটি মূল্যের রেফারেন্স বোঝায়। মান উল্লেখগুলি কেবলমাত্র অস্থায়ী বস্তুর সাথে আবদ্ধ হবে, অন্যথায় স্পষ্টভাবে উত্পন্ন না হলে। এগুলি নির্দিষ্ট পরিস্থিতিতে আইটেমগুলিকে আরও বেশি দক্ষ করতে এবং নিখুঁত ফরোয়ার্ডিং হিসাবে পরিচিত এমন একটি সুবিধা সরবরাহ করতে ব্যবহৃত হয় যা টেমপ্লেট কোডকে ব্যাপকভাবে সরল করে।

সি ++ 03 এ আপনি একটি অ-পরিবর্তনীয় লভ্যালু এবং কোনও মূল্যমানের অনুলিপিটির মধ্যে পার্থক্য করতে পারবেন না।

std::string s;
std::string another(s);           // calls std::string(const std::string&);
std::string more(std::string(s)); // calls std::string(const std::string&);

সি ++ 0 এক্সে, এটি কেস নয়।

std::string s;
std::string another(s);           // calls std::string(const std::string&);
std::string more(std::string(s)); // calls std::string(std::string&&);

এই নির্মাণকারীদের পিছনে বাস্তবায়ন বিবেচনা করুন। প্রথম ক্ষেত্রে, স্ট্রিংকে মান শব্দার্থিকতা ধরে রাখতে একটি অনুলিপি সম্পাদন করতে হয়, যার মধ্যে একটি নতুন গাদা বরাদ্দ জড়িত। যাইহোক, দ্বিতীয় ক্ষেত্রে, আমরা আগে থেকেই জানি যে আমাদের কন্সট্রাক্টরের কাছে যে বস্তুটি দেওয়া হয়েছিল তা ধ্বংসের জন্য অবিলম্বে হয় এবং এটি অচ্ছুত থাকতে হবে না। আমরা কার্যকরভাবে কেবল অভ্যন্তরীণ পয়েন্টারগুলিকে অদলবদল করতে পারি এবং এই দৃশ্যে কোনও অনুলিপি সম্পাদন করতে পারি না, যা যথেষ্ট পরিমাণে দক্ষ। স্থানান্তরিত পদক্ষেপগুলি এমন কোনও শ্রেণীর উপকৃত হয় যার অভ্যন্তরীণভাবে উল্লেখযোগ্য সংস্থানগুলি ব্যয়বহুল বা নিষিদ্ধ প্রতিলিপি রয়েছে cop এর ক্ষেত্রে বিবেচনা করুন std::unique_ptr- এখন যেহেতু আমাদের শ্রেণি অস্থায়ী এবং অ-অস্থায়ীগুলির মধ্যে পার্থক্য করতে পারে, আমরা পদক্ষেপ শব্দার্থকে সঠিকভাবে কাজ করতে পারি যাতে unique_ptrঅনুলিপি করা যায় না তবে সরানো যায়, যার অর্থstd::unique_ptrআইনীভাবে স্ট্যান্ডার্ড পাত্রে, বাছাই করা ইত্যাদি ইত্যাদিতে সংরক্ষণ করা যেতে পারে, তবে সি ++ 03 এর std::auto_ptrপারে না।

এখন আমরা মূল্যবোধের রেফারেন্সের অন্যান্য ব্যবহার বিবেচনা করি - নিখুঁত ফরওয়ার্ডিং। একটি রেফারেন্সের জন্য একটি রেফারেন্স বাইন্ডিংয়ের প্রশ্নটি বিবেচনা করুন।

std::string s;
std::string& ref = s;
(std::string&)& anotherref = ref; // usually expressed via template

C ++ 03 এ সম্পর্কে কী বলে তা মনে করতে পারছি না, তবে সি ++ 0 এক্স-এ, মূল্যমানের রেফারেন্সগুলির সাথে ডিল করার সময় ফলাফল প্রকারটি গুরুত্বপূর্ণ। টাইপ টির সাথে একটি মূল রেফারেন্স, যেখানে টি একটি রেফারেন্স টাইপ, টাইপ টি-এর একটি রেফারেন্স হয়ে যায়

(std::string&)&& ref // ref is std::string&
(const std::string&)&& ref // ref is const std::string&
(std::string&&)&& ref // ref is std::string&&
(const std::string&&)&& ref // ref is const std::string&&

সবচেয়ে সহজ টেমপ্লেট ফাংশন বিবেচনা করুন - সর্বনিম্ন এবং সর্বাধিক। সি ++ 03 এ আপনাকে ম্যানুয়ালি কনস্ট এবং নন-কনস্টের চারটি সংমিশ্রণের জন্য ওভারলোড করতে হবে। সি ++ 0 এক্সে এটি কেবল একটি ওভারলোড। বৈকল্পিক টেম্পলেটগুলির সাথে মিলিত, এটি নিখুঁত ফরোয়ার্ডিং সক্ষম করে।

template<typename A, typename B> auto min(A&& aref, B&& bref) {
    // for example, if you pass a const std::string& as first argument,
    // then A becomes const std::string& and by extension, aref becomes
    // const std::string&, completely maintaining it's type information.
    if (std::forward<A>(aref) < std::forward<B>(bref))
        return std::forward<A>(aref);
    else
        return std::forward<B>(bref);
}

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


আপনি কেন ব্যবহার করেছেন std::forward<A>(aref) < std::forward<B>(bref)? এবং আমি মনে করি না যে আপনি যখন এগিয়ে যান int&এবং চেষ্টা করেন তখন এই সংজ্ঞাটি সঠিক হবে float&। এক ধরণের ফর্ম টেম্পলেট থেকে ভাল ড্রপ।
ইয়ানকেস

25

T&& টাইপ ছাড়ের সাথে (যেমন নিখুঁত ফরওয়ার্ডিংয়ের জন্য) ব্যবহৃত হয় তার জন্য শব্দটি ফরওয়ার্ডিং রেফারেন্স হিসাবে আড়ম্বরপূর্ণভাবে পরিচিত । "সর্বজনীন রেফারেন্স" শব্দটি স্কট মায়ার্স এই নিবন্ধে তৈরি করেছিলেন , তবে পরে এটি পরিবর্তন করা হয়েছিল।

কারণ এটি আর-মান বা এল-মান হতে পারে।

উদাহরণগুলি হ'ল:

// template
template<class T> foo(T&& t) { ... }

// auto
auto&& t = ...;

// typedef
typedef ... T;
T&& t = ...;

// decltype
decltype(...)&& t = ...;

এর উত্তরে আরও আলোচনার সন্ধান পাওয়া যাবে: সর্বজনীন রেফারেন্সের জন্য সিনট্যাক্স


14

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

void foo(X& x);  // lvalue reference overload
void foo(X&& x); // rvalue reference overload

X x;
X foobar();

foo(x);        // argument is lvalue: calls foo(X&)
foo(foobar()); // argument is rvalue: calls foo(X&&)

সুতরাং একটি মূল্যবান কি? যে কোনও কিছুতেই মূল্য নেই। লভ্যালু এমন একটি অভিব্যক্তি যা মেমোরি অবস্থানকে বোঝায় এবং & অপারেটরের মাধ্যমে সেই মেমরির অবস্থানের ঠিকানা নিতে আমাদের অনুমতি দেয়।

প্রথমে মূল্যায়নগুলি উদাহরণ দিয়ে কী অর্জন করে তা বোঝা প্রায় সহজ:

 #include <cstring>
 class Sample {
  int *ptr; // large block of memory
  int size;
 public:
  Sample(int sz=0) : ptr{sz != 0 ? new int[sz] : nullptr}, size{sz} 
  {
     if (ptr != nullptr) memset(ptr, 0, sz);
  }
  // copy constructor that takes lvalue 
  Sample(const Sample& s) : ptr{s.size != 0 ? new int[s.size] :\
      nullptr}, size{s.size}
  {
     if (ptr != nullptr) memcpy(ptr, s.ptr, s.size);
     std::cout << "copy constructor called on lvalue\n";
  }

  // move constructor that take rvalue
  Sample(Sample&& s) 
  {  // steal s's resources
     ptr = s.ptr;
     size = s.size;        
     s.ptr = nullptr; // destructive write
     s.size = 0;
     cout << "Move constructor called on rvalue." << std::endl;
  }    
  // normal copy assignment operator taking lvalue
  Sample& operator=(const Sample& s)
  {
   if(this != &s) {
      delete [] ptr; // free current pointer
      size = s.size;

      if (size != 0) {
        ptr = new int[s.size];
        memcpy(ptr, s.ptr, s.size);
      } else 
         ptr = nullptr;
     }
     cout << "Copy Assignment called on lvalue." << std::endl;
     return *this;
  }    
 // overloaded move assignment operator taking rvalue
 Sample& operator=(Sample&& lhs)
 {
   if(this != &s) {
      delete [] ptr; //don't let ptr be orphaned 
      ptr = lhs.ptr;   //but now "steal" lhs, don't clone it.
      size = lhs.size; 
      lhs.ptr = nullptr; // lhs's new "stolen" state
      lhs.size = 0;
   }
   cout << "Move Assignment called on rvalue" << std::endl;
   return *this;
 }
//...snip
};     

কন্সট্রাক্টর এবং অ্যাসাইনমেন্ট অপারেটরগুলি সংস্করণগুলির সাথে ওভারলোড হয়ে গেছে যা মানগুলি রেফারেন্স নেয়। "আমাকে কি কোনও মূল্যমান বা কোনও মূল্যমান বলা হচ্ছে?" শর্তে মূল্যের উল্লেখগুলি সংকলনের সময় (ওভারলোড রেজোলিউশনের মাধ্যমে) একটি ফাংশনকে শাখার অনুমতি দেয়। এটি আমাদের আরও দক্ষ কন্সট্রাক্টর এবং অ্যাসাইনমেন্ট অপারেটর তৈরি করার অনুমতি দেয় যা সরানো সংস্থানগুলির পরিবর্তে সেগুলি অনুলিপি করে।

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

সংশ্লেষ: মূলসূত্র উল্লেখগুলি পদার্থ পদক্ষেপের অনুমতি দেয় (এবং নিখুঁত নিবন্ধের লিঙ্কে আলোচিত নিখুঁত ফরোয়ার্ডিং)।

একটি ব্যবহারিক সহজেই বোঝার উদাহরণ ক্লাস টেম্পলেট std :: অনন্য_পিটার । যেহেতু একটি অনন্য_পাত্র তার অন্তর্নিহিত কাঁচা পয়েন্টারটির একচেটিয়া মালিকানা বজায় রাখে, তাই অনন্য_পিটার অনুলিপি করা যায় না। এটি তাদের একচেটিয়া মালিকানার আক্রমণকারীকে লঙ্ঘন করবে। সুতরাং তাদের অনুলিপি নির্মাণকারী নেই। তবে তাদের কাছে মুভ কনস্ট্রাক্টর রয়েছে:

template<class T> class unique_ptr {
  //...snip
 unique_ptr(unique_ptr&& __u) noexcept; // move constructor
};

 std::unique_ptr<int[] pt1{new int[10]};  
 std::unique_ptr<int[]> ptr2{ptr1};// compile error: no copy ctor.  

 // So we must first cast ptr1 to an rvalue 
 std::unique_ptr<int[]> ptr2{std::move(ptr1)};  

std::unique_ptr<int[]> TakeOwnershipAndAlter(std::unique_ptr<int[]> param,\
 int size)      
{
  for (auto i = 0; i < size; ++i) {
     param[i] += 10;
  }
  return param; // implicitly calls unique_ptr(unique_ptr&&)
}

// Now use function     
unique_ptr<int[]> ptr{new int[10]};

// first cast ptr from lvalue to rvalue
unique_ptr<int[]> new_owner = TakeOwnershipAndAlter(\
           static_cast<unique_ptr<int[]>&&>(ptr), 10);

cout << "output:\n";

for(auto i = 0; i< 10; ++i) {
   cout << new_owner[i] << ", ";
}

output:
10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 

static_cast<unique_ptr<int[]>&&>(ptr)সাধারণত std :: মুভ ব্যবহার করে করা হয়

// first cast ptr from lvalue to rvalue
unique_ptr<int[]> new_owner = TakeOwnershipAndAlter(std::move(ptr),0);

চমৎকার একটি নিবন্ধ সব এই এবং ব্যাখ্যা আরও বেশি (মত কিভাবে rvalues নিখুঁত ফরওয়ার্ডিং এবং মানে কি অনুমতি দেয়) ভাল উদাহরণ প্রচুর সঙ্গে টমাস বেকার কারো নির্দেশ চলে না সি ++ Rvalue তথ্যসূত্র ব্যাখ্যা । এই পোস্টটি তার নিবন্ধ উপর প্রচুর নির্ভর করে।

একটি সংক্ষিপ্ত ভূমিকা হ'ল স্ট্রুট্রুপ দ্বারা মূল্যায়ন রেফারেন্স সংক্ষিপ্ত পরিচিতি , এবং। আল


কপিরাইট Sample(const Sample& s)কনট্রাক্টর এর বিষয়বস্তু অনুলিপি করা প্রয়োজন হয় না? 'অনুলিপি অ্যাসাইনমেন্ট অপারেটর' এর জন্য একই প্রশ্ন।
কে.ক্রামাজেন

হ্যাঁ তুমিই ঠিক. আমি স্মৃতি কপি করতে ব্যর্থ। কপি কনস্ট্রাক্টর এবং কপি অ্যাসাইনমেন্ট অপারেটর উভয়ই সেই আকারের পরীক্ষার পরে মেমকিপি (পিটিআর, এস.পি.পি., আকার) করতে হবে! = 0. এবং ডিফল্ট কনস্ট্রাক্টরের মাপ হলে মেমসেট (পিটিআর, 0, আকার) করা উচিত! = 0.
কুর্ট krueckeberg

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