কেন হেডারে সি ++ ইনলাইন ফাংশন রয়েছে?


120

এনবি এটি কীভাবে ইনলাইন ফাংশনগুলি ব্যবহার করবেন বা কীভাবে তারা কাজ করে সে সম্পর্কে আরও প্রশ্ন নয়, আরও বেশি কারণ তারা কীভাবে হয়।

শ্রেণি সদস্যের ক্রিয়াকলাপের ঘোষণার জন্য কোনও ফাংশনকে সংজ্ঞায়িত করার দরকার নেই inline, এটি কেবলমাত্র ফাংশনটির বাস্তব বাস্তবায়ন। উদাহরণস্বরূপ, শিরোলেখ ফাইলটিতে:

struct foo{
    void bar(); // no need to define this as inline
}

সুতরাং কেন একটি ক্লাস ইনলাইন বাস্তবায়ন ফাংশন আছে আছে হেডার ফাইলে হতে? আমি কেন ইনলাইন ফাংশনটি .cppফাইলটি রাখতে পারি না ? যদি আমি .cppফাইলটিতে ইনলাইন সংজ্ঞাটি রাখার চেষ্টা করি তবে আমি এর লাইনগুলিতে একটি ত্রুটি পেয়ে যাব:

error LNK2019: unresolved external symbol 
"public: void __thiscall foo::bar(void)"
(?bar@foo@@QAEXXZ) referenced in function _main 
1>C:\Users\Me\Documents\Visual Studio 2012\Projects\inline\Debug\inline.exe 
: fatal error LNK1120: 1 unresolved externals



@ চারেলস আমি বলব যে দ্বিতীয় লিঙ্কটি আমার অনুরূপ হতে পারে তবে কেন ইনলাইন সেভাবে কাজ করে তার পিছনে যুক্তি সম্পর্কে আরও জিজ্ঞাসা করছি।
thecoshman

2
সেক্ষেত্রে, আমি মনে করি আপনি "ইনলাইন" বা "শিরোনাম ফাইলগুলি" ভুল বুঝে থাকতে পারেন; আপনার বক্তব্য দুটিও সত্য নয়। আপনার কোনও সদস্য ফাংশনের একটি ইনলাইন বাস্তবায়ন থাকতে পারে এবং আপনি একটি শিরোনাম ফাইলে ইনলাইন ফাংশন সংজ্ঞা রাখতে পারেন, এটি কেবল ভাল ধারণা নয়। আপনি আপনার প্রশ্ন পরিষ্কার করতে পারেন?
সিবি বেইলি

সম্পাদনা পোস্ট করুন, আমি মনে করি আপনি যখন inlineসংজ্ঞাতে উপস্থিত হন তবে পরিস্থিতি সম্পর্কে জিজ্ঞাসা করছেন তবে পূর্বের ঘোষণার বিপরীতে নয় । যদি তা হয় তবে এটি সহায়তা করতে পারে: stackoverflow.com/questions/4924912/…
সিবি বেইলি

উত্তর:


122

কোনও inlineফাংশনটির সংজ্ঞাটি একটি শিরোনাম ফাইলে থাকতে হবে না তবে ইনলাইন ফাংশনগুলির জন্য একটি সংজ্ঞা বিধি ( ওডিআর ) এর কারণে, এটি ব্যবহৃত প্রতিটি অনুবাদ ইউনিটে ফাংশনের জন্য একটি অভিন্ন সংজ্ঞা থাকতে হবে।

এটি অর্জনের সবচেয়ে সহজ উপায় হ'ল হেডার ফাইলটিতে সংজ্ঞা স্থাপন করা।

আপনি যদি কোনও ফাংশনের সংজ্ঞাটি একটি একক উত্স ফাইলে রাখতে চান তবে আপনার এটি প্রকাশ করা উচিত নয় inline। ঘোষিত না হওয়া কোনও ফাংশনটির inlineঅর্থ এই নয় যে সংকলকটি ফাংশনটি ইনলাইন করতে পারে না।

আপনার কোনও ক্রিয়াকলাপটি ঘোষণাকালীন হওয়া উচিত inlineবা না তা সাধারণত এমন একটি পছন্দ যা আপনার অনুসরণ করা উচিত এমন একটি সংজ্ঞা নিয়মের কোন সংস্করণটির ভিত্তিতে আপনার অনুসরণ করা উচিত; যোগ করা inlineএবং তারপরে পরবর্তী সীমাবদ্ধতাগুলি দ্বারা সীমাবদ্ধ হওয়া কোনও অর্থবোধ করে না।


কিন্তু সংকলক .cpp ফাইলটি সংকলন করে না, যার মধ্যে .h ফাইলগুলি অন্তর্ভুক্ত রয়েছে ... যাতে এটি যখন একটি .cpp ফাইল সংকলন করে তখন এতে হতাশার পাশাপাশি উত্স ফাইল উভয়ই থাকে। টানা অন্যান্য শিরোনাম ফাইলগুলি কেবল তাদের যাতে
সংকলকটি

1
এটি আমার চেয়ে আমার চেয়ে অনেক বেশি ভাল উত্তর +1!
sbi

2
@ থেকোশম্যান: দুটি পার্থক্য রয়েছে। উত্স ফাইল বনাম শিরোনাম ফাইল। কনভেনশন দ্বারা, একটি শিরোনাম ফাইলটি সাধারণত একটি উত্স ফাইলকে বোঝায় যা কোনও অনুবাদ ইউনিটের ভিত্তিতে নয় তবে কেবল অন্য উত্স ফাইল থেকে অন্তর্ভুক্ত। তারপরে ডিক্লেয়ারেশন বনাম সংজ্ঞা রয়েছে। শিরোনাম ফাইল বা 'সাধারণ' উত্স ফাইলগুলিতে ফাংশনগুলির বিবৃতি বা সংজ্ঞা থাকতে পারে। আমি ভীত আমি আপনার মন্তব্যে যা জিজ্ঞাসা করছেন তা নিশ্চিত নই।
সিবি বেইলি

চিন্তা করবেন না, আমি কেন এটি এখন পেয়েছি ... যদিও আমি নিশ্চিত নই যে এই উত্তরটি আসলে কী দিয়েছে। আপনার এবং @ জানাটোসের উত্তরের সংমিশ্রণটি এটি আমার জন্য ব্যাখ্যা করেছে।
thecoshman

113

এটি দেখার দুটি উপায় রয়েছে:

  1. ইনলাইন ফাংশনগুলি শিরোনামে সংজ্ঞায়িত করা হয় কারণ কোনও ফাংশন কলকে ইনलाइन করার জন্য, সংকলকটি অবশ্যই ফাংশন বডি দেখতে সক্ষম হতে হবে। এটি করার জন্য কোনও নির্দোষ সংকলকটির জন্য, ফাংশন বডিটি কল হিসাবে একই অনুবাদ ইউনিটে থাকতে হবে। (একটি আধুনিক সংকলক অনুবাদ ইউনিটগুলি জুড়ে অনুকূলিত করতে পারে, এবং ফাংশন সংজ্ঞাটি পৃথক অনুবাদ ইউনিটে থাকলেও একটি ফাংশন কল অন্তর্ভুক্ত করা যেতে পারে, তবে এই অপটিমাইজেশনগুলি ব্যয়বহুল, সর্বদা সক্ষম নয়, এবং সর্বদা সমর্থন করে না কম্পাইলার)

  2. শিরোনামে সংজ্ঞায়িত ফাংশনগুলি অবশ্যই চিহ্নিত করতে হবে inlineকারণ অন্যথায়, প্রতিটি অনুবাদ ইউনিটে যার মধ্যে শিরোলেখ অন্তর্ভুক্ত থাকে সেগুলি ফাংশনের একটি সংজ্ঞা থাকবে এবং লিঙ্কার একাধিক সংজ্ঞা (এক সংজ্ঞা বিধি লঙ্ঘন) সম্পর্কে অভিযোগ করবে। inlineশব্দ এই শুষে, একাধিক অনুবাদ ইউনিট (অভিন্ন) সংজ্ঞা ধারণ করতে সক্ষম হবেন।

দুটি ব্যাখ্যা সত্যিই এই সত্যে ফুটে উঠেছে যে inlineকীওয়ার্ডটি আপনি যা আশা করেছিলেন তা ঠিক তেমন করে না।

একটি সি ++ সংকলক ইনলাইনিং অপ্টিমাইজেশান প্রয়োগ করতে পারবেন (কল করা ওভারহেডটি কল করে ফাংশনটির শরীরের সাথে ফাংশন কলকে প্রতিস্থাপন করুন) যতক্ষণ না এটি প্রোগ্রামের পর্যবেক্ষণযোগ্য আচরণকে পরিবর্তন করে না।

inlineশব্দ তোলে আরও সহজ ফাংশন সংজ্ঞা একাধিক অনুবাদ এককে দৃশ্যমান করতে সক্ষম হবেন, কিন্তু শব্দ ব্যবহার কম্পাইলার মানে এই নয় এই অপ্টিমাইজেশান প্রয়োগ করতে, কম্পাইলার জন্য করেনি ফাংশন ইনলাইন, এবং না শব্দ ব্যবহার না সংকলকটিকে ফাংশনটি অন্তর্ভুক্ত করতে নিষেধ করুন।


23

এটি সি ++ কম্পাইলারের একটি সীমা। আপনি যদি শিরোনামটিতে ফাংশনটি রেখে দেন, সমস্ত সিপিপি ফাইল যেখানে এটি ইনলাইন করা যায় সেগুলি আপনার ফাংশনের "উত্স" দেখতে পারে এবং সংকলক দ্বারা ইনলাইনিং করা যেতে পারে। ইনলাইনিংটি লিঙ্কার দ্বারা সম্পন্ন করতে হবে (প্রতিটি সিপিপি ফাইল পৃথকভাবে একটি আপজ ফাইলে সংকলিত হয়)। সমস্যাটি হ'ল লিঙ্কারে এটি করা আরও বেশি কঠিন। "টেমপ্লেট" শ্রেণি / ফাংশনগুলির সাথে একই ধরণের সমস্যা বিদ্যমান। তাদের সংকলক দ্বারা তাত্ক্ষণিক করা প্রয়োজন, কারণ লিঙ্কারে তাদের তাত্ক্ষণিকভাবে (একটি বিশেষায়িত সংস্করণ তৈরি করতে) সমস্যা হবে। কিছু নতুন সংকলক / লিঙ্কার একটি "দুটি পাস" সংকলন / সংযোগ করতে পারে যেখানে সংকলকটি প্রথম পাস করে, তারপরে লিঙ্কারটি তার কাজটি করে এবং অমীমাংসিত জিনিসগুলি সমাধান করার জন্য সংকলকটিকে কল করে (ইনলাইন / টেম্পলেট ...)


আচ্ছা বুঝলাম! হ্যাঁ, এটি শ্রেণীর জন্য নয় এটি নিজেরাই ইনলাইন ফাংশনটি ব্যবহার করে, এর অন্যান্য কোড যা ইনলাইন ফাংশনগুলি ব্যবহার করে। তারা কেবল ক্লাসের জন্য শিরোনামের ফাইলটি ইনলাইন করা হচ্ছে!
thecoshman

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

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

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

10

কারণটি হ'ল সংকলকটিকে কলটির জায়গায় ফেলে দিতে সক্ষম হওয়ার জন্য সংজ্ঞাটি আসলে দেখতে হবে।

মনে রাখবেন যে সি এবং সি ++ একটি খুব সরল সংকলন মডেল ব্যবহার করে, যেখানে সংকলকটি সর্বদা একটি সময়ে কেবল একটি অনুবাদ ইউনিট দেখে। (এটি রফতানিতে ব্যর্থ হয়েছে, এটিই মূল কারণ যা কেবলমাত্র একজন বিক্রেতা বাস্তবে এটি প্রয়োগ করে implemented)


9

সি ++ inlineকীওয়ার্ডটি বিভ্রান্তিমূলক, এর অর্থ "এই ফাংশনটি ইনলাইন করা" নয়। যদি কোনও ফাংশনটিকে ইনলাইন হিসাবে সংজ্ঞায়িত করা হয়, তবে এর সহজরূপে অর্থ হ'ল যতক্ষণ না সমস্ত সংজ্ঞা সমান হয় ততক্ষণ এটি একাধিকবার সংজ্ঞায়িত হতে পারে। এমন কোনও ফাংশন হিসাবে চিহ্নিত inlineহওয়ার জন্য এটি একেবারে আইনী, যেখানে ডাকা হয় সেই স্থানে কোডটি ইনলাইনড করার পরিবর্তে বলা হয় function

টেমপ্লেটগুলির জন্য শিরোনাম ফাইলে একটি ফাংশন সংজ্ঞায়িত করা প্রয়োজন, যেহেতু একটি টেম্প্লেটেড ক্লাসটি আসলে কোনও শ্রেণি নয়, এটি একটি শ্রেণীর জন্য একটি টেম্পলেট যা আপনি একাধিক প্রকারের পরিবর্তন করতে পারেন। উদাহরণস্বরূপ, যখন আপনি কোনও ফু ক্লাস তৈরি করতে ফু টেম্পলেটটি ব্যবহার করেন তখন কোনও সংকলক কোনও Foo<int>::bar()ফাংশন তৈরি করতে সক্ষম হওয়ার জন্য , এর আসল সংজ্ঞাটি অবশ্যই দৃশ্যমান হবে।Foo<T>::bar()


এবং যেহেতু এটি কোনও শ্রেণীর জন্য একটি টেম্পলেট , তাই এটি একটি টেম্পলেট শ্রেণি বলা হয় না , তবে একটি শ্রেণীর টেম্পলেট
sbi

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

কিছু সংকলক এটি একটি ইঙ্গিত হিসাবে ব্যবহার করবে যাতে ফাংশনটি সম্ভবত সম্ভবত অন্তর্ভুক্ত করা যেতে পারে তবে আপনি এটি ঘোষণা করার কারণে এটি অন্তর্ভুক্ত হওয়ার গ্যারান্টিযুক্ত নয় inline(বা এটি ঘোষণা করা হয়নি inlineযে এটি গ্যারান্টি দেয় না))
কিথ এম

4

আমি জানি এটি একটি পুরানো থ্রেড তবে ভেবেছিলাম আমার externকীওয়ার্ডটি উল্লেখ করা উচিত । আমি সম্প্রতি এই সমস্যাটিতে এসেছি এবং নীচের মত সমাধান করেছি

Helper.h

namespace DX
{
    extern inline void ThrowIfFailed(HRESULT hr);
}

Helper.cpp

namespace DX
{
    inline void ThrowIfFailed(HRESULT hr)
    {
        if (FAILED(hr))
        {
            std::stringstream ss;
            ss << "#" << hr;
            throw std::exception(ss.str().c_str());
        }
    }
}

6
আপনি পুরো প্রোগ্রাম অপটিমাইজেশন (ডাব্লুপিও) ব্যবহার না করা হলে এটি সাধারণত ফাংশনটিতে প্রকৃতপক্ষে অন্তর্ভুক্ত হয় না।
চক ওয়ালবর্ন

3

কারণ সংকলকটি তাদের ইনলাইন করার জন্য তাদের দেখতে হবে । এবং শিরোনাম ফাইলগুলি হ'ল "উপাদানগুলি" যা সাধারণত অন্য অনুবাদ ইউনিটে অন্তর্ভুক্ত থাকে।

#include "file.h"
// Ok, now me (the compiler) can see the definition of that inline function. 
// So I'm able to replace calls for the actual implementation.

1

ইনলাইন ফাংশন

সি ++ এ একটি ম্যাক্রো ইনলাইন ফাংশন ছাড়া কিছুই নয়। সুতরাং এখন ম্যাক্রোগুলি সংকলকের নিয়ন্ত্রণে রয়েছে।

  • গুরুত্বপূর্ণ : আমরা শ্রেণীর ভিতরে কোনও ফাংশন সংজ্ঞায়িত করলে তা স্বয়ংক্রিয়ভাবে ইনলাইন হয়ে যাবে

ইনলাইন ফাংশনের কোডটিকে বলা হয় সেই স্থানে প্রতিস্থাপন করা হয়, সুতরাং এটি কলিং ফাংশনের ওভারহেড হ্রাস করে।

কিছু ক্ষেত্রে ফাংশনটির ইনলাইনিং কাজ করতে পারে না, যেমন

  • যদি স্ট্যাটিক ভেরিয়েবল ইনলাইন ফাংশনের অভ্যন্তরে ব্যবহৃত হয়।

  • ফাংশন জটিল হলে।

  • ফাংশন পুনরাবৃত্তি কল যদি

  • যদি কার্যের ঠিকানাটি সুস্পষ্টভাবে বা স্পষ্টভাবে নেওয়া হয়

নীচের হিসাবে শ্রেণীর বাইরে সংজ্ঞায়িত ফাংশন ইনলাইন হয়ে যেতে পারে

inline int AddTwoVar(int x,int y); //This may not become inline 

inline int AddTwoVar(int x,int y) { return x + y; } // This becomes inline

শ্রেণীর ভিতরে সংজ্ঞায়িত ফাংশনটিও ইনলাইন হয়ে যায়

// Inline SpeedMeter functions
class SpeedMeter
{
    int speed;
    public:
    int getSpeed() const { return speed; }
    void setSpeed(int varSpeed) { speed = varSpeed; }
};
int main()
{
    SpeedMeter objSM;
    objSM.setSpeed(80);
    int speedValue = A.getSpeed();
} 

এখানে getSpeed ​​এবং setSpeed ​​ফাংশন উভয়ই ইনলাইন হয়ে যাবে


হ্যাঁ, কিছু সুন্দর তথ্য সম্ভবত, তবে কেন তা ব্যাখ্যা করার চেষ্টা করে না । আপনি করতে পারেন, কিন্তু কেবল এটি পরিষ্কার করে দিচ্ছেন না।
thecoshman

2
নিম্নলিখিত বিবৃতিটি সত্য নয়: "গুরুত্বপূর্ণ: আমরা শ্রেণীর অভ্যন্তরে কোনও ফাংশন সংজ্ঞায়িত করলে তা স্বয়ংক্রিয়ভাবে ইনলাইন হয়ে যাবে" আপনি ঘোষণার / সংজ্ঞায় "ইনলাইন" লিখলেও তা নিশ্চিত হতে পারবেন না যে এটি বাস্তবে অন্তর্ভুক্ত রয়েছে being এমনকি টেমপ্লেটগুলির জন্যও নয়। সম্ভবত আপনি বোঝাতে চেয়েছিলেন যে সংকলকটি স্বয়ংক্রিয়ভাবে "ইনলাইন" কীওয়ার্ডটি ধরে নিয়েছে, তবুও অনুসরণ করতে হবে না এবং আমি যা লক্ষ্য করেছি তা হ'ল বেশিরভাগ ক্ষেত্রে এটি এ জাতীয় শিরোনামের সংজ্ঞাগুলিকে ইনলাইন করে না, এমনকি সাধারণ কনটেক্সট ফাংশনের জন্যও নয় not বুনিয়াদি গণিত।
পাবলো অ্যারিল

আরে মন্তব্যের জন্য ধন্যবাদ ... নীচে সি ++ micc.unifi.it/bertini/download/programmazione/… পৃষ্ঠা 400 এ চিন্তাভাবনা থেকে লাইনগুলি আছে .. দয়া করে চেক করুন .. আপনি যদি সম্মত হন তবে দয়া করে উত্সাহ দিন । ধন্যবাদ ..... ক্লাসের অভ্যন্তরে ইনলাইনগুলি একটি ইনলাইন ফাংশন সংজ্ঞায়িত করতে, আপনাকে অবশ্যই ইনলাইন কীওয়ার্ড সহ ফাংশন সংজ্ঞাটি পূর্ববর্তী করতে হবে। যাইহোক, এটি কোনও শ্রেণির সংজ্ঞার ভিতরে প্রয়োজন হয় না। শ্রেণীর সংজ্ঞায় আপনি যে ফাংশনটি সংজ্ঞায়িত করেন তা হ'ল স্বয়ংক্রিয়ভাবে একটি ইনলাইন।
সৌরভ রাউত

বইটির লেখকরা যা চান তা দাবি করতে পারেন, কারণ তারা বই লেখেন, কোড নয়। আমার পোর্টেবল 3 ডি ডেমোকে যতটা সম্ভব ইনডিল কোডটি এড়িয়ে 64৪ কেবি এরও কম ফিট করতে এটির জন্য আমাকে গভীরভাবে বিশ্লেষণ করতে হয়েছিল। প্রোগ্রামিং হ'ল তথ্য সম্পর্কিত, না ধর্ম সম্পর্কিত, সুতরাং কিছু "গড প্রোগ্রামার" এটি কোনও বইতে বলেছে, যদি এটি অনুশীলনে ঘটে যা প্রতিনিধিত্ব না করে তবে এটি কোনও বিষয় নয়। এবং বেশিরভাগ সি ++ বইয়ের মধ্যে খারাপ পরামর্শের সংকলন রয়েছে, যা সময়ে সময়ে আপনাকে আপনার রেপেটেরিতে যুক্ত করার জন্য কিছু ঝরঝরে কৌশল খুঁজে পেতে পারে।
পাবলো অ্যারিয়েল

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