কনস্টের সম্পর্কিত মূল্যবোধের রেফারেন্সগুলির কোনও ব্যবহার আছে?


89

আমি অনুমান করি না, তবে আমি নিশ্চিত করতে চাই। সেখানে কোনো ব্যবহার কি const Foo&&, যেখানে Fooএকটি বর্গ আর কী লিখব?


4
এই ভিডিওতে, এসটিএল বলেছেন const&&খুব গুরুত্বপূর্ণ, যদিও তিনি তা বলেন না: youtube.com/watch?v=JhgWFYfdIho#t=54m20s
অ্যারন ম্যাকডেইড

উত্তর:


78

এগুলি মাঝে মাঝে উপকারী। সি ++ 0x খসড়া নিজেই এগুলিকে কয়েকটি জায়গায় ব্যবহার করে, উদাহরণস্বরূপ:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

উপরের দুটি ওভারলোডগুলি নিশ্চিত করে যে অন্য ref(T&)এবং cref(const T&)ফাংশনগুলি মূল্যের সাথে আবদ্ধ না হয় (যা অন্যথায় সম্ভব হবে)।

হালনাগাদ

আমি স্রেফ অফিসিয়াল স্ট্যান্ডার্ড এন 3290 পরীক্ষা করেছি , যা দুর্ভাগ্যক্রমে সর্বজনীনভাবে উপলভ্য নয় এবং এটিতে 20.8 ফাংশন অবজেক্টস [ ফাংশন.বজেক্টস ] / পি 2 রয়েছে:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

তারপরে আমি সর্বাধিক সাম্প্রতিক পোস্টের সি ++ 11 খসড়াটি চেক করেছিলাম, যা সর্বজনীনভাবে উপলব্ধ, N3485 , এবং 20.8 ফাংশন অবজেক্টস [ ফাংশন.অবজেক্টস ] / পি 2 তে এখনও এটি বলে:

template <class T> void ref(const T&&) = delete;
template <class T> void cref(const T&&) = delete;

সিপ্রেফারেন্সের দিকে তাকালে মনে হয় এটি আর হয় না। কোন ধারণা কেন? অন্য কোন স্থান const T&&ব্যবহার করা হয়?
পাব্বি

60
আপনি নিজের উত্তরটিতে একই কোডটি কেন তিনবার অন্তর্ভুক্ত করলেন? আমি খুব দীর্ঘ সময়ের জন্য একটি পার্থক্য সন্ধান করার চেষ্টা করেছি।
টাইপ 1232

9
@ typ1232: মনে হচ্ছে যে রেফারেন্সড ফাংশনগুলি আর হাজির হবে না এমন মন্তব্যে উদ্বেগের কারণে আমি উত্তরটি উত্তর দেওয়ার প্রায় 2 বছর পরে উত্তর আপডেট করেছি। আমি N3290 থেকে একটি অনুলিপি / পেস্ট করেছি এবং তত্কালীনতম খসড়া N3485 থেকে দেখিয়েছি যে কার্যগুলি এখনও উপস্থিত রয়েছে। আমার কপিরাইট / পেস্ট ব্যবহার করা, সেই সময়ে মনে মনে ছিল যে আমার চেয়ে আরও বেশি চোখ নিশ্চিত করতে পারে যে আমি এই স্বাক্ষরগুলিতে কিছুটা ছোটখাটো পরিবর্তন উপেক্ষা করছি না।
হাওয়ার্ড হিন্যান্ট

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

4
ব্যবহারের const T&&প্রতিরোধ কারো বোকার মত ফর্মের স্পষ্ট টেমপ্লেট args ব্যবহার ref<const A&>(...)। এটি কোনও ভয়ঙ্কর দৃ strong় যুক্তি নয়, তবে const T&&ওভারের T&&ব্যয়টি বেশ ন্যূনতম।
হাওয়ার্ড হিন্যান্ট

6

কনস্ট কনভুল্য রেফারেন্স (এবং এর জন্য নয় =delete) পাওয়ার শব্দার্থবিজ্ঞানের কথাটি হল:

  • আমরা ল্যাভালুদের জন্য অপারেশনকে সমর্থন করি না!
  • তবুও, আমরা এখনও অনুলিপি করি , কারণ আমরা পাস করা সংস্থানটি স্থানান্তর করতে পারি না , বা এটি "সরানোর" জন্য কোনও আসল অর্থ নেই বলে।

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


কেস: কাঁচা পয়েন্টার থেকে স্মার্ট পয়েন্টার নির্মাণকারী

এটি সাধারণত ব্যবহার করার পরামর্শ দেওয়া হবে make_uniqueএবং make_sharedতবে উভয়ই unique_ptrএবং shared_ptrকাঁচা পয়েন্টার থেকে তৈরি করা যেতে পারে। উভয় কনস্ট্রাক্টর মান দ্বারা পয়েন্টার পেতে এবং এটি অনুলিপি। উভয়ই অনুমতি দেয় (অর্থাত্ এই অর্থে: প্রতিরোধ করবেন না ) মূল পয়েন্টারটির ধারাবাহিকতা ব্যবহার তাদের কাছে কনস্ট্রাক্টরে পৌঁছেছে।

নিম্নলিখিত কোডটি দ্বৈত ফ্রি সহ সংকলন এবং ফলাফল :

int* ptr = new int(9);
std::unique_ptr<int> p { ptr };
// we forgot that ptr is already being managed
delete ptr;

উভয়ই unique_ptrএবং shared_ptrউপরোক্ত প্রতিরোধ করতে পারে যদি তাদের প্রাসঙ্গিক নির্মাণকারীরা কাঁচা পয়েন্টারটি কনস্টের মূল্য হিসাবে যেমন প্রত্যাশা করে তবে এটির জন্য unique_ptr:

unique_ptr(T* const&& p) : ptr{p} {}

কোন ক্ষেত্রে উপরের ডাবল ফ্রি কোডটি সংকলন করবে না, তবে নিম্নলিখিতগুলি নিম্নলিখিতটি করবে:

std::unique_ptr<int> p1 { std::move(ptr) }; // more verbose: user moves ownership
std::unique_ptr<int> p2 { new int(7) };     // ok, rvalue

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


একজন জিজ্ঞাসা করতে পারেন: ঠিক আছে, তবে কেন T* কনস্ট&& p ?

কারণটি সহজ, unique_ptr কনস্ট পয়েন্টার থেকে তৈরি করার অনুমতি দেওয়া । মনে রাখবেন যে const rvalue রেফারেন্স শুধু চেয়ে বেশি জেনেরিক হয় rvalue রেফারেন্স হিসাবে এটিকে স্বীকার করলে উভয় constএবং non-const। সুতরাং আমরা নিম্নলিখিত অনুমতি দিতে পারেন:

int* const ptr = new int(9);
auto p = std::unique_ptr<int> { std::move(ptr) };

এটি কেবলমাত্র আমরা যদি বিচার সংক্রান্ত রেফারেন্সটি আশা করি (সংকলন ত্রুটি: কনস্ট রাল্যুকে মূল্যকে বেঁধে রাখতে পারে না ) go


যাইহোক, এই জাতীয় জিনিস প্রস্তাব করতে খুব দেরী হয়েছে। তবে এই ধারণাটি কনস্টের কাছে কোনও মূল্যের রেফারেন্সের যুক্তিসঙ্গত ব্যবহার উপস্থাপন করে ।


আমি একই মত ধারণাগুলিযুক্ত লোকদের মধ্যে ছিলাম, তবে এগিয়ে যাওয়ার পক্ষে আমার সমর্থন ছিল না।
রেড.ওয়েভ

"অটো পি = স্টেডি :: অনন্য_পিটার {স্টডি :: মুভ (পিটিআর)};" "শ্রেণীর টেম্পলেট আর্গুমেন্ট ছাড়ের ব্যর্থতা" ত্রুটি দিয়ে সংকলন করে না আমি মনে করি এটি "অনন্য_পাত্র <int>" হওয়া উচিত।
জেহুই লিন

4

এগুলি অনুমোদিত এবং এমনকি ফাংশনগুলির উপর ভিত্তি করে র‌্যাঙ্কিং করা হয় const, তবে যেহেতু আপনি কনস্টের অবজেক্টের দ্বারা উল্লেখ করেছেন তা সরানো যায় না const Foo&&, সেগুলি কার্যকর নয়।


"র‌্যাঙ্কড" মন্তব্য দিয়ে ঠিক কী বোঝ? ওভারলোড রেজোলিউশনের সাথে কিছু করার জন্য, আমার ধারণা?
ফ্রেডওভারফ্লো

কেন আপনি কোনও কনস্টেন্ট রালু-রেফ থেকে সরতে পারেন না, যদি প্রদত্ত ধরণের একটি মুভ সিটার থাকে যা কোনও কনস্ট কনভালিউ-রেফ নেয়?
ফ্রেড নুরক

6
@ ফ্রেড ওভারফ্লো, ওভারলোডের র‌্যাঙ্কিংটি হ'ল:const T&, T&, const T&&, T&&
জিন বুশুয়েভ

4
@ ফ্রেড: উত্সটি পরিবর্তন না করে আপনি কীভাবে চলাচল করবেন?
ফ্রেডওভারফ্লো

4
@ ফ্রেড: পরিবর্তনীয় ডেটা সদস্য, বা সম্ভবত এই অনুমানমূলক ধরণের জন্য চলার জন্য ডেটা সদস্যদের পরিবর্তন করার প্রয়োজন নেই require
ফ্রেড নুরক

2

স্ট্যান্ড :: রেফারেন্স ছাড়াও , স্ট্যান্ডার্ড লাইব্রেরি একই উদ্দেশ্যে স্ট্যান্ড :: as_const এ কনস্ট রুল্যু রেফারেন্সও ব্যবহার করে।

template <class T>
void as_const(const T&&) = delete;

মোড়কের মান পাওয়ার সময় এটি স্ট্যান্ড :: বিকল্পে রিটার্ন মান হিসাবেও ব্যবহৃত হয়:

constexpr const T&& operator*() const&&;
constexpr const T&& value() const &&;

পাশাপাশি স্ট্যান্ডে :: পান :

template <class T, class... Types>
constexpr const T&& get(const std::variant<Types...>&& v);
template< class T, class... Types >
constexpr const T&& get(const tuple<Types...>&& t) noexcept;

মোটা মানটি অ্যাক্সেস করার সময় মানটি বিভাগের সাথে সাথে মোড়কের দৃ const়তা বজায় রাখার জন্য এটি সম্ভবত।

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


1

আমি এমন পরিস্থিতিতে ভাবতে পারি না যেখানে এটি সরাসরি কার্যকর হবে তবে এটি পরোক্ষভাবে ব্যবহার করা যেতে পারে:

template<class T>
void f(T const &x) {
  cout << "lvalue";
}
template<class T>
void f(T &&x) {
  cout << "rvalue";
}

template<class T>
void g(T &x) {
  f(T());
}

template<class T>
void h(T const &x) {
  g(x);
}

টি মধ্যে হয় টি const, তাই এর এক্স একটি টি const && হয়।

এটি একটি comile ভুলবশত সম্ভবত এই ফলাফল হল (যখন এটি সরানো বা অবজেক্ট ব্যবহার করার চেষ্টা করে), কিন্তু (তাই একটি rvalue-সুত্র গ্রহণ করতে পারে খুব সহজ হিসেবে rvalue পরিবর্তন ছাড়া যে এটি lvalues উপর বলা যায় না উদাহরণস্বরূপ)।

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