প্রশ্নে থাকা ল্যাম্বদার আসলে কোনও রাজ্য নেই ।
পরীক্ষা করা:
struct lambda {
auto operator()() const { return 17; }
};
এবং যদি আমাদের ছিল lambda f;
, এটি একটি খালি শ্রেণি। উপরেরগুলি কেবল lambda
আপনার ল্যাম্বদার মতোই নয়, এটি (মূলত) আপনার ল্যাম্বদা কীভাবে প্রয়োগ করা হয়! (এটি পয়েন্টার অপারেটর কাজ করতে একটি অন্তর্নিহিত কাস্টেরও প্রয়োজন, এবং নামটি lambda
কয়েকটি সংকলক-উত্পাদিত সিউডো-গাইডের সাথে প্রতিস্থাপিত হতে চলেছে)
সি ++ এ, অবজেক্টগুলি পয়েন্টার নয়। তারা প্রকৃত জিনিস। তারা কেবলমাত্র তাদের মধ্যে ডেটা সংরক্ষণের জন্য প্রয়োজনীয় স্থানটি ব্যবহার করে। একটি বস্তুর পয়েন্টার একটি বস্তুর চেয়ে বড় হতে পারে।
আপনি যদি কোনও ল্যাম্বডাকে কোনও ফাংশনের পয়েন্টার হিসাবে মনে করতে পারেন, তবে তা নয়। আপনি auto f = [](){ return 17; };
কোনও আলাদা ফাংশন বা ল্যাম্বডায় পুনরায় সাইন করতে পারবেন না !
auto f = [](){ return 17; };
f = [](){ return -42; };
উপরে অবৈধ । কোন জায়গা নেই f
স্টোরে যা ফাংশন বলা হতে যাচ্ছে - যে তথ্য সংরক্ষণ করা হয় টাইপ এর f
, মূল্য না f
!
আপনি যদি এটি করেন:
int(*f)() = [](){ return 17; };
অথবা এটা:
std::function<int()> f = [](){ return 17; };
আপনি আর সরাসরি ল্যাম্বডা সংরক্ষণ করছেন না। এই উভয় ক্ষেত্রেই f = [](){ return -42; }
আইনী - সুতরাং এই ক্ষেত্রে আমরা কোন ফাংশনটির মান বিবেচনা করছি তা সংরক্ষণ করছি f
। এবং sizeof(f)
এটি আর নয় 1
, বরং sizeof(int(*)())
বড় বা বৃহত্তর (মূলত, পয়েন্টার আকারের বা বৃহত্তর হবেন, যেমনটি আপনি প্রত্যাশা করেন std::function
একটি ন্যূনতম মাপটি মান দ্বারা সূচিত হয় (তারা একটি নির্দিষ্ট আকার পর্যন্ত "নিজের ভিতরে" কল করতে সক্ষম হন)) যা অনুশীলনে ফাংশন পয়েন্টার হিসাবে অন্তত বৃহত্তর)।
সেক্ষেত্রে int(*f)()
আপনি কোনও ফাংশন পয়েন্টার এমন কোনও ফাংশনে সংরক্ষণ করছেন যা যদি সেই ল্যাম্বডাকে ডাকে। এটি কেবল স্টেটলেস ল্যাম্বডাসের জন্য কাজ করে (খালি []
ক্যাপচার তালিকার সাথে রয়েছে)।
সেক্ষেত্রে std::function<int()> f
আপনি একটি টাইপ-ইরেজরের ক্লাসের std::function<int()>
উদাহরণ তৈরি করছেন যে (এই ক্ষেত্রে) একটি অভ্যন্তরীণ বাফারে আকার -1 ল্যাম্বদার একটি অনুলিপি সংরক্ষণ করতে নতুন স্থান ব্যবহার করে (এবং, যদি একটি বৃহত্তর ল্যাম্বদা পাস করা হয় (আরও রাষ্ট্রের সাথে) ), হিপ বরাদ্দ ব্যবহার করবে)।
অনুমান হিসাবে, এই জাতীয় কিছু সম্ভবত আপনার মনে হয় যা চলছে। যে একটি ল্যাম্বদা এমন একটি বস্তু যার প্রকারের স্বাক্ষর দ্বারা বর্ণনা করা হয়। C ++, এটা lambdas করতে সিদ্ধান্ত নেওয়া হয় শূন্য খরচ ম্যানুয়াল ফাংশন বস্তুর বাস্তবায়ন উপর বিমূর্ত। এটি আপনাকে একটি ল্যাম্বডাকে একটি std
অ্যালগরিদম (বা অনুরূপ) এ পাস করতে দেয় এবং যখন এটি অ্যালগরিদম টেম্পলেটটি ইনস্ট্যান্ট করে তখন এর সামগ্রীগুলি সংকলকটিতে পুরোপুরি দৃশ্যমান হয়। যদি কোনও ল্যাম্বদার মতো ধরণের থাকে তবে std::function<void(int)>
এর সামগ্রীগুলি সম্পূর্ণরূপে দৃশ্যমান হবে না এবং একটি হস্ত-কারুকৃত ফাংশন অবজেক্টটি দ্রুত হতে পারে।
সি ++ মানককরণের লক্ষ্য হ'ল ক্র্যাফ্টেড সি কোডের ওপরে শূন্য ওভারহেড সহ উচ্চ স্তরের প্রোগ্রামিং।
এখন যেহেতু আপনি বুঝতে পেরেছেন যে f
বাস্তবে আপনি রাষ্ট্রহীন, আপনার মাথায় আরও একটি প্রশ্ন থাকা উচিত: ল্যাম্বডারের কোনও রাজ্য নেই। কেন এটি আকার হয় না 0
?
সংক্ষিপ্ত উত্তর আছে।
সি ++ এর সমস্ত বস্তুর মানের নীচে ন্যূনতম আকার 1 থাকতে হবে এবং একই ধরণের দুটি অবজেক্টের একই ঠিকানা থাকতে পারে না। এগুলি সংযুক্ত, কারণ ধরণের অ্যারেতে T
উপাদানগুলি sizeof(T)
পৃথক পৃথক করে রাখা হবে ।
এখন এটির কোনও রাজ্য না থাকায় এটি কখনও কখনও স্থান গ্রহণ করতে পারে না। এটি "একা" থাকলে এটি ঘটতে পারে না, তবে কিছু প্রসঙ্গে এটি ঘটতে পারে। std::tuple
এবং অনুরূপ লাইব্রেরি কোড এই সত্যটিকে কাজে লাগায়। এটা যেভাবে কাজ করে:
যেহেতু একটি ল্যাম্বডা operator()
অতিরিক্ত লোডযুক্ত শ্রেণীর সমতুল্য , স্টেটলেস ল্যাম্বডাস ( []
ক্যাপচার তালিকার সাথে) সমস্ত খালি ক্লাস। তারা আছে sizeof
এর 1
। প্রকৃতপক্ষে, আপনি যদি তাদের কাছ থেকে উত্তরাধিকারী হন (যা অনুমোদিত!) তবে তারা এতক্ষণ কোনও স্থান গ্রহণ করবে না কারণ এটি কোনও একই ধরণের ঠিকানার সংঘর্ষের কারণ না করে । (এটি খালি বেস অপ্টিমাইজেশন হিসাবে পরিচিত)।
template<class T>
struct toy:T {
toy(toy const&)=default;
toy(toy &&)=default;
toy(T const&t):T(t) {}
toy(T &&t):T(std::move(t)) {}
int state = 0;
};
template<class Lambda>
toy<Lambda> make_toy( Lambda const& l ) { return {l}; }
এটি sizeof(make_toy( []{std::cout << "hello world!\n"; } ))
হ'ল sizeof(int)
(ভাল, উপরেরটি অবৈধ কারণ আপনি মূল্যায়ন-না-করা প্রেক্ষাপটে ল্যাম্বদা তৈরি করতে পারবেন না: আপনাকে একটি নাম তৈরি করতে হবে auto toy = make_toy(blah);
তবে করুক sizeof(blah)
, তবে এটি কেবল গোলমাল)। sizeof([]{std::cout << "hello world!\n"; })
এখনও 1
(অনুরূপ যোগ্যতা) হয়।
যদি আমরা অন্য খেলনা টাইপ তৈরি করি:
template<class T>
struct toy2:T {
toy2(toy2 const&)=default;
toy2(T const&t):T(t), t2(t) {}
T t2;
};
template<class Lambda>
toy2<Lambda> make_toy2( Lambda const& l ) { return {l}; }
এই ল্যাম্বডা দুটি কপি আছে । তারা একই ঠিকানা ভাগ করতে পারে না, sizeof(toy2(some_lambda))
হয় 2
!
struct
সহoperator()
) হিসাবে বাস্তবায়িত হয়েছে