`Constexpr` এবং` কনস্টের মধ্যে পার্থক্য `


593

মধ্যে পার্থক্য কি constexprএবং const?

  • আমি কখনই তাদের একটি ব্যবহার করতে পারি?
  • আমি কখন উভয় ব্যবহার করতে পারি এবং কীভাবে আমার একটি নির্বাচন করা উচিত?

71
constexprএকটি সংকলন-সময় ধ্রুবক তৈরি করে; constসহজভাবে মানে যে মান পরিবর্তন করা যায় না।
0x499602D2


থেকে এই নিবন্ধটি হতে boost/hanaগ্রন্থাগার কিছু enlight করতে constexprসমস্যা যেখানে আপনি ব্যবহার করতে পারেন constexprএবং যেখানে তুমি পারবে না: boost.org/doc/libs/1_69_0/libs/hana/doc/html/...
Andry

@ 0x499602D2 " কেবল এর মানে হল যে মান পরিবর্তন করা যাবে না " একটি স্কেলার একটি আক্ষরিক সঙ্গে সক্রিয়া, একটি মান হতে পারে না যে পরিবর্তন হয় একটি কম্পাইল সময় ধ্রুবক।
কৌতূহলী

@ কুরিয়াসগুয়ে হ্যাঁ আমার মন্তব্যটি খুব প্রশমিত করা হয়েছিল। স্বীকারোক্তিযুক্ত আমি তখন constexprফিরে এসেছি নতুন :)
0x499602D2

উত্তর:


587

বেসিক অর্থ এবং বাক্য গঠন

উভয় কীওয়ার্ড অবজেক্টের ঘোষণার পাশাপাশি ফাংশনগুলিতে ব্যবহার করা যেতে পারে। বস্তুর ক্ষেত্রে প্রয়োগ করার সময় মূল পার্থক্যটি হ'ল:

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

  • constexpr স্ট্যান্ডার্ড যা কল করে তার জন্য উপযুক্ত হিসাবে কোনও বস্তু ঘোষণা করে ধ্রুবক এক্সপ্রেশনগুলি । তবে মনে রাখবেন যে constexprএটি করার একমাত্র উপায় নয়।

যখন প্রয়োগ করা হয় ফাংশনে হলে মূল পার্থক্যটি হ'ল:

  • constশুধুমাত্র অ স্থিতিশীল সদস্য ফাংশনগুলির জন্য ব্যবহার করা যেতে পারে, সাধারণভাবে ফাংশন নয়। এটি গ্যারান্টি দেয় যে সদস্য ফাংশনটি অ স্থিতিশীল ডেটা সদস্যদের কোনওটিকেই সংশোধন করে না।

  • constexprউভয় সদস্য এবং অ-সদস্য ফাংশন, পাশাপাশি নির্মাণকারীদের সাথে ব্যবহার করা যেতে পারে। এটি ধ্রুবক অভিব্যক্তিগুলিতে ব্যবহারের জন্য উপযুক্ত ফাংশন ঘোষণা করে । সংকলক কেবল তখনই এটি গ্রহণ করবে যদি ফাংশনটি নির্দিষ্ট মানদণ্ড (7.1.5 / 3,4) মাপে, সর্বাধিক গুরুত্বপূর্ণভাবে (†) :

    • ফাংশন বডিটি অবশ্যই অ-ভার্চুয়াল এবং চূড়ান্ত সাধারণ হওয়া উচিত: টাইপডেফ এবং স্ট্যাটিক সংস্থাগুলি ব্যতীত কেবল একটি একক return বিবৃতি অনুমোদিত। কোনও কনস্ট্রাক্টরের ক্ষেত্রে কেবল একটি সূচনা তালিকা, টাইপডেফ এবং স্ট্যাটিক এ্যাসার্ট অনুমোদিত। ( = defaultএবং= delete অনুমোদিত, এছাড়াও, যদিও।)
    • সি ++ ১৪ অনুসারে নিয়মগুলি আরও স্বাচ্ছন্দ্যযুক্ত, তখন থেকে কনস্টেক্সপ্রেশ ফাংশনের ভিতরে কী অনুমোদিত: asmঘোষণা, একটিgoto বিবৃতি, caseএবং অন্য কোনও লেবেল সহ একটি বিবৃতিdefault , অ-আক্ষরিক ধরণের বৈকল্পিকের সংজ্ঞা, স্ট্যাটিক বা থ্রেড স্টোরেজ সময়কালের একটি চলকের সংজ্ঞা, একটি চলকের সংজ্ঞা যার জন্য কোনও আরম্ভ করা হয় না।
    • আর্গুমেন্ট এবং রিটার্নের ধরণ অবশ্যই আক্ষরিক ধরণের হতে হবে (যেমন, সাধারণভাবে বলা যায়, খুব সাধারণ ধরণের, সাধারণত স্কেলার বা সমষ্টি)

ধ্রুব প্রকাশ

উপরে যেমন বলা হয়েছে, constexprধ্রুবক অভিব্যক্তিগুলিতে ব্যবহারের জন্য উপযুক্ত হিসাবে উভয় অবজেক্টের পাশাপাশি কার্যকারিতা ঘোষণা করে। একটি ধ্রুবক অভিব্যক্তি নিছক ধ্রুবকের চেয়ে বেশি:

  • এটি এমন জায়গাগুলিতে ব্যবহার করা যেতে পারে যেখানে সংকলন-সময় মূল্যায়ন প্রয়োজন, উদাহরণস্বরূপ, টেম্পলেট প্যারামিটার এবং অ্যারে-আকার নির্দিষ্টকরণকারী:

    template<int N>
    class fixed_size_list
    { /*...*/ };
    
    fixed_size_list<X> mylist;  // X must be an integer constant expression
    
    int numbers[X];  // X must be an integer constant expression
  • তবে দ্রষ্টব্য:

    • constexprকোনও কিছু হিসাবে ঘোষণা করা গ্যারান্টিযুক্ত নয় যে এটি সংকলন সময়ে মূল্যায়ন করা হবে। এটি এর জন্য ব্যবহার করা যেতে পারে তবে এটি রান-টাইমে মূল্যায়ন করা অন্যান্য জায়গাগুলিতেও ব্যবহার করা যেতে পারে।

    • একটি বস্তু হতে পারে ধ্রুবক এক্সপ্রেশন ব্যবহারের জন্য মাপসই করা ছাড়া ঘোষিত হওয়ার constexpr। উদাহরণ:

      int main()
      {
        const int N = 3;
        int numbers[N] = {1, 2, 3};  // N is constant expression
      }

    এটি সম্ভব কারণ কারণ N, আক্ষরিক সাথে ঘোষণার সময় ধ্রুবক এবং সূচনা হওয়া, এটি ঘোষিত না হলেও স্থির অভিব্যক্তির মানদণ্ডকে সন্তুষ্ট করে constexpr

সুতরাং আমি কখন ব্যবহার করতে হবে constexpr?

  • উপরের মতো কোনও বস্তু ঘোষিত না করেN ধ্রুবক অভিব্যক্তি হিসাবে ব্যবহার করা যেতে পারে । এটি সমস্ত বস্তুর ক্ষেত্রে সত্য:constexpr

    • const
    • অবিচ্ছেদ্য বা গণনা প্রকার এবং
    • ঘোষণার সময় একটি প্রকাশের সাথে আরম্ভ করা যা নিজেই একটি ধ্রুবক প্রকাশ

    [এটি §5.19 / 2 এর কারণে: একটি অবিচ্ছিন্ন অভিব্যক্তিটিতে এমন একটি subexpresstions অন্তর্ভুক্ত করা উচিত না যে "অবমূল্যায়ন বা গণনার প্রকারের […] অবদান না […]" রিচার্ড স্মিথকে আমার সংশোধন করার জন্য ধন্যবাদ পূর্ববর্তী দাবি যে এটি সমস্ত আক্ষরিক ধরণের জন্য সত্য ছিল]

  • ধ্রুবক অভিব্যক্তিগুলিতে কোনও ফাংশনটি ব্যবহারের জন্য উপযুক্ত হওয়ার জন্য এটি অবশ্যই স্পষ্টভাবে ঘোষণা করতে হবে constexpr; কেবল ধ্রুবক-প্রকাশের ক্রিয়াকলাপগুলির জন্য মানদণ্ডগুলি পূরণ করার পক্ষে এটি পর্যাপ্ত নয়। উদাহরণ:

    template<int N>
    class list
    { };
    
    constexpr int sqr1(int arg)
    { return arg * arg; }
    
    int sqr2(int arg)
    { return arg * arg; }
    
    int main()
    {
      const int X = 2;
      list<sqr1(X)> mylist1;  // OK: sqr1 is constexpr
      list<sqr2(X)> mylist2;  // wrong: sqr2 is not constexpr
    }

কখন / আমি উভয় constএবং একসাথে ব্যবহার করতে পারি constexpr ?

উ: বস্তু ঘোষণায় এটি কখনই প্রয়োজন হয় না যখন উভয় কীওয়ার্ড ঘোষিত হওয়ার জন্য একই বস্তুকে বোঝায়। constexprবোঝা const

constexpr const int N = 5;

হিসাবে একই

constexpr int N = 5;

তবে নোট করুন এমন পরিস্থিতিতে থাকতে পারে যখন কীওয়ার্ডগুলি ঘোষণার বিভিন্ন অংশকে বোঝায়:

static constexpr int N = 3;

int main()
{
  constexpr const int *NP = &N;
}

এখানে, NPঠিকানা স্থির-প্রকাশ হিসাবে ঘোষিত হয়, অর্থাত্ একটি পয়েন্টার যা নিজেই একটি ধ্রুবক অভিব্যক্তি। (স্থিতিশীল / বৈশ্বিক ধ্রুবক অভিব্যক্তিতে ঠিকানা অপারেটর প্রয়োগ করে যখন ঠিকানাটি উত্পন্ন হয় তখন এটি সম্ভব হয়)) এখানে উভয়ই constexprএবং constপ্রয়োজনীয়: constexprসর্বদা ঘোষিত (এখানে NP) প্রকাশিত হওয়াটিকে constবোঝায় , যখন intএটি নির্দেশক- টু-const)। অপসারণটি constঅভিব্যক্তিটিকে অবৈধভাবে রেন্ডার করে (কারণ (ক) অ-কনস্ট্যান্ট অবজেক্টের পয়েন্টার একটি ধ্রুবক প্রকাশ হতে পারে না, এবং (খ) &Nপ্রকৃতপক্ষে পয়েন্টার-টু-ধ্রুবক)।

সদস্য পদে ঘোষণাপত্রে বি। সি ++ 11 এ constexprবোঝায় const, যখন সি ++ 14 এবং সি ++ 17 তে এটি হয় না। সি ++ 11 এর অধীনে ঘোষিত সদস্য ফাংশন

constexpr void f();

হিসাবে ঘোষণা করা প্রয়োজন

constexpr void f() const;

constক্রিয়াকলাপ হিসাবে এখনও ব্যবহারযোগ্য হওয়ার জন্য সি ++ এর অধীনে


3
আইএমও "সংকলনের সময় অগত্যা মূল্যায়ন করা হয় না" তাদের "সংকলনের সময় মূল্যায়ন করা" হিসাবে ভাবার চেয়ে কম সহায়ক। ধ্রুবক অভিব্যক্তিগুলির প্রতিবন্ধকতাগুলির অর্থ হ'ল কোনও সংকলকটির জন্য এটি মূল্যায়ন করা তুলনামূলকভাবে সহজ। এই সংবন্ধগুলি সন্তুষ্ট না হলে একটি সংকলক অবশ্যই অভিযোগ করতে হবে। যেহেতু কোনও পার্শ্ব প্রতিক্রিয়া নেই, তাই কোনও সংকলক এটি "মূল্যায়ন" করেছে কিনা তা আপনি কখনই কোনও পার্থক্য বলতে পারবেন না।
aschepler

10
পছন্দ করুন আমার মূল বক্তব্যটি হ'ল আপনি যদি constexprঅবিচ্ছিন্ন অভিব্যক্তি হিসাবে কোনও ফাংশনটি কল করেন , যেমন একটি সাধারণ পরিবর্তনশীল, এটি পুরোপুরি আইনী এবং ফাংশনটি অন্য ফাংশনের মতো ব্যবহার করা হবে। সংকলনের সময় এটি মূল্যায়ন করা হবে না (কারণ এটি পারে না)। সম্ভবত আপনি সম্ভবত এটি সুস্পষ্ট মনে করেন - তবে আমি যদি বলেছি যে constexprসংঘটিত সময়ে কোনও ঘোষিত ফাংশন সর্বদা মূল্যায়ন করা হয়, তবে এটি ভুল উপায়ে ব্যাখ্যা করা যেতে পারে।
jogojapan

5
হ্যাঁ, আমি constexprবস্তুর কথা বলছিলাম , ফাংশন নয়। আমি constexprমূল্যবোধগুলির সংকলনের সময় মূল্যায়নের জন্য জোর করে এবং constexprফাংশনগুলিকে সংকলন সময় বা উপযুক্ত সময় হিসাবে চালনার সময় মূল্যায়ন করার অনুমতি দেওয়ার জন্য বিষয়গুলির বিষয়ে ভাবতে চাই ।
aschepler

2
একটি সংশোধন: 'কনস্ট' কেবলমাত্র একটি সীমাবদ্ধতা যা আপনি ভেরিয়েবলের মান পরিবর্তন করতে পারবেন না; এটি কোনও প্রতিশ্রুতি দেয় না যে মানটি বদলাবে না (যেমন, অন্য কারও দ্বারা)। এটি একটি লেখার সম্পত্তি, পড়ার সম্পত্তি নয়।
জারেড গ্রুব

3
এই বাক্য: এটি একটি গ্যারান্টি দেয় যে সদস্য ফাংশনটি অ স্থিতিশীল ডেটা সদস্যদের কোনওটিকেই সংশোধন করে না। একটি গুরুত্বপূর্ণ বিবরণ মিস করে। চিহ্নিত হিসাবে সদস্যদের সদস্য ফাংশন mutableদ্বারা সংশোধন করা যেতে পারে const
সর্বনাশ

119

constভেরিয়েবলের জন্য প্রযোজ্য এবং তাদের আপনার কোডে পরিবর্তন হতে বাধা দেয়

constexprসংকলককে বলে যে এই অভিব্যক্তিটি একটি সংকলন সময় ধ্রুবক মান হিসাবে ফলাফল , সুতরাং এটি অ্যারে দৈর্ঘ্য, constভেরিয়েবল বরাদ্দকরণ ইত্যাদির মতো জায়গায় ব্যবহার করা যেতে পারে । অলি দ্বারা প্রদত্ত লিঙ্কটিতে প্রচুর চমৎকার উদাহরণ রয়েছে।

মূলত এগুলি পুরোপুরি 2 টি ভিন্ন ধারণা এবং একসাথে ব্যবহার করা যেতে পারে (এবং হওয়া উচিত)।


2
কনস্ট্যান্ট এবং কনটেক্সট্রপ্র ব্যবহার, উদাঃ en.cppreferences.com/w/cpp/container/array/get
মনোহর রেড্ডি পোরেডি

64

সংক্ষিপ্ত বিবরণ

  • constগ্যারান্টি দেয় যে কোনও প্রোগ্রাম কোনও জিনিসের মান পরিবর্তন করে না । যাইহোক, constবস্তুটি কোন ধরণের সূচনার গ্যারান্টি দেয় না।

    বিবেচনা:

    const int mx = numeric_limits<int>::max();  // OK: runtime initialization

    ফাংশনটি max()কেবল একটি আক্ষরিক মান দেয়। তবে, যেহেতু ইনিশিয়ালাইজারটি একটি ফাংশন কল, তাই mxরানটাইম ইনিশিয়েশনের মধ্য দিয়ে যায়। সুতরাং, আপনি এটি একটি ধ্রুবক প্রকাশ হিসাবে ব্যবহার করতে পারবেন না :

    int arr[mx];  // error: “constant expression required”
  • constexprএকটি নতুন সি ++ 11 কীওয়ার্ড যা আপনাকে ম্যাক্রোগুলি এবং হার্ডকোডযুক্ত আক্ষরিক তৈরির প্রয়োজনীয়তা থেকে মুক্তি দেয়। এটি নির্দিষ্ট শর্তেও গ্যারান্টি দেয় যে বস্তুগুলি স্থিতিশীলভাবে আরম্ভ হয় । এটি একটি অভিব্যক্তির মূল্যায়নের সময়কে নিয়ন্ত্রণ করে। এর প্রকাশের সংকলন-সময় মূল্যায়ন প্রয়োগের মাধ্যমে , constexprআপনাকে সংশোধন -সময় স্থির উপর নির্ভর করে এমন কোনও কোডে টাইম-ক্রিটিকাল অ্যাপ্লিকেশন, সিস্টেম প্রোগ্রামিং, টেম্পলেট এবং সাধারণভাবে বলার জন্য গুরুত্বপূর্ণ ধ্রুবক অভিব্যক্তি সংজ্ঞা দিতে দেয় ।

ধ্রুবক-এক্সপ্রেশন ফাংশন

একটি ধ্রুবক-এক্সপ্রেশন ফাংশন ঘোষিত একটি ফাংশন constexpr। এর দেহটি অবশ্যই অ-ভার্চুয়াল হতে হবে এবং টাইপেডেফ এবং স্ট্যাটিক সংস্থাগুলি ব্যতীত কেবল একটি একক রিটার্নের বিবৃতি নিয়ে গঠিত। এটির আর্গুমেন্ট এবং রিটার্ন মানের অবশ্যই আক্ষরিক প্রকার থাকতে হবে। এটি অ-ধ্রুবক-প্রকাশের যুক্তিগুলির সাথে ব্যবহার করা যেতে পারে, তবে যখন এটি সম্পন্ন হয় ফলাফলটি ধ্রুবক প্রকাশ নয় not

একটি ধ্রুবক-এক্সপ্রেশন ফাংশনটি পারফরম্যান্স বা টাইপ সুরক্ষা ছাড়াই ম্যাক্রো এবং হার্ডকোডযুক্ত আক্ষরিক প্রতিস্থাপন করে to

constexpr int max() { return INT_MAX; }           // OK
constexpr long long_max() { return 2147483647; }  // OK
constexpr bool get_val()
{
    bool res = false;
    return res;
}  // error: body is not just a return statement

constexpr int square(int x)
{ return x * x; }  // OK: compile-time evaluation only if x is a constant expression
const int res = square(5);  // OK: compile-time evaluation of square(5)
int y = getval();
int n = square(y);          // OK: runtime evaluation of square(y)

কনস্ট্যান্ট-এক্সপ্রেশন অবজেক্টস

একটি ধ্রুবক-অভিব্যক্তি অবজেক্ট একটি ঘোষিত বস্তু constexpr। এটি অবশ্যই একটি ধ্রুবক অভিব্যক্তি বা ধ্রুবক-অভিব্যক্তি যুক্তিযুক্ত ধ্রুবক-এক্সপ্রেশন কন্সট্রাক্টর দ্বারা নির্মিত একটি মূল্য দিয়ে শুরু করা উচিত।

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

struct S
{
    constexpr int two();      // constant-expression function
private:
    static constexpr int sz;  // constant-expression object
};
constexpr int S::sz = 256;
enum DataPacket
{
    Small = S::two(),  // error: S::two() called before it was defined
    Big = 1024
};
constexpr int S::two() { return sz*2; }
constexpr S s;
int arr[s.two()];  // OK: s.two() called after its definition

কনস্ট্যান্ট-এক্সপ্রেশন কনস্ট্রাক্টর

একটি ধ্রুবক-প্রকাশের কনস্ট্রাক্টর একটি নির্ধারক হিসাবে ঘোষণা করা হয় constexpr। এটিতে সদস্যের সূচনা তালিকা থাকতে পারে তবে এটির দেহ অবশ্যই টাইপেফ এবং স্থিতিশীল সংস্থাগুলি ব্যতীত খালি থাকতে হবে। এর যুক্তিগুলিতে আক্ষরিক ধরণের থাকতে হবে।

একটি ধ্রুবক-এক্সপ্রেশন কনস্ট্রাক্টর কম্পাইলারকে সংকলন-সময়ে বস্তুটি আরম্ভ করার অনুমতি দেয়, তবে শর্ত থাকে যে কনস্ট্রাক্টরের আর্গুমেন্টগুলি সমস্ত ধ্রুবক এক্সপ্রেশন।

struct complex
{
    // constant-expression constructor
    constexpr complex(double r, double i) : re(r), im(i) { }  // OK: empty body
    // constant-expression functions
    constexpr double real() { return re; }
    constexpr double imag() { return im; }
private:
    double re;
    double im;
};
constexpr complex COMP(0.0, 1.0);         // creates a literal complex
double x = 1.0;
constexpr complex cx1(x, 0);              // error: x is not a constant expression
const complex cx2(x, 1);                  // OK: runtime initialization
constexpr double xx = COMP.real();        // OK: compile-time initialization
constexpr double imaglval = COMP.imag();  // OK: compile-time initialization
complex cx3(2, 4.6);                      // OK: runtime initialization

স্কট মায়ার্স সম্পর্কিত কার্যকর আধুনিক সি ++ বইয়ের টিপস constexpr:

  • constexpr অবজেক্টগুলি কনস্ট এবং সংকলনের সময় পরিচিত মানগুলির সাথে আরম্ভ করা হয়;
  • constexpr ফাংশনগুলি সংকলনের সময় ফলাফলগুলি উত্পন্ন করে যখন আর্গুমেন্টগুলির সাথে ডাকা হয় যার মূল্য সংকলনের সময় জানা যায়;
  • constexprঅবজেক্টস এবং ফাংশনগুলি অ- constexprঅবজেক্টস এবং ফাংশনগুলির তুলনায় বিস্তৃত প্রেক্ষাপটে ব্যবহার করা যেতে পারে ;
  • constexpr কোনও বস্তুর বা ফাংশনের ইন্টারফেসের অংশ।

উত্স: সি ++ তে সুরক্ষা, পারফরম্যান্স এবং এনক্যাপসুলেশন উন্নত করতে কনটেক্সপ্র ব্যবহার করা


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

35

এর "সি ++ ল্যাঙ্গুয়েজ 4th Editon প্রোগ্রামিং" দ্বারা বিয়ারনে স্ট্রোভস্ট্রুপের বই অনুসারে
const মোটামুটিভাবে অর্থ '' আমি এই মান পরিবর্তন করতে না প্রতিজ্ঞা '' (§7.5।): এটি প্রাথমিকভাবে ইন্টারফেসগুলি নির্দিষ্ট করতে ব্যবহৃত হয়, যাতে ডেটা পরিবর্তিত হওয়ার আশঙ্কা ছাড়াই ফাংশনে প্রেরণ করা যায়।
সংকলক কনস্টের দ্বারা করা প্রতিশ্রুতি কার্যকর করে।
constexpr : মোটামুটিভাবে অর্থ '' (§10.4) 'কম্পাইল সময়ে মূল্যায়ন করা হয়'। এটি প্রাথমিকভাবে কনস্ট্যান্ট নির্দিষ্ট করতে ব্যবহৃত হয়,
উদাহরণস্বরূপ:

const int dmv = 17; // dmv is a named constant
int var = 17; // var is not a constant
constexpr double max1 = 1.4*square(dmv); // OK if square(17) is a constant expression
constexpr double max2 = 1.4square(var); // error : var is not a constant expression
const double max3 = 1.4square(var); //OK, may be evaluated at run time
double sum(const vector<double>&); // sum will not modify its argument (§2.2.5)
vector<double> v {1.2, 3.4, 4.5}; // v is not a constant
const double s1 = sum(v); // OK: evaluated at run time
constexpr double s2 = sum(v); // error : sum(v) not constant expression

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

constexpr double square(double x) { return xx; }


কনটেক্সপ্রপ হওয়ার জন্য, একটি ফাংশনটি অবশ্যই সহজ হতে হবে: একটি মানকে গণনা করে কেবল একটি রিটার্ন-স্টেটমেন্ট। অবিচ্ছিন্ন আর্গুমেন্টের জন্য একটি কনটেক্সট্রপ ফাংশন ব্যবহার করা যেতে পারে, তবে এটি যখন সম্পন্ন হয় তখন ফলটি একটি ধ্রুবক প্রকাশ নয়। ধ্রুবক প্রকাশের প্রয়োজন হয় না এমন প্রসঙ্গে কনটেক্সটপ্রিপ ফাংশনটিকে অ ধ্রুবক-অভিব্যক্তি যুক্তি যুক্ত করার জন্য আমরা অনুমতি দিই, যাতে আমরা একই ফাংশনটি দু'বার সংজ্ঞায়িত করতে না পারি: একবার ধ্রুবক অভিব্যক্তির জন্য এবং একবার ভেরিয়েবলের জন্য।
কয়েকটি স্থানে অবিচ্ছিন্ন প্রকাশের প্রয়োজন ভাষা নিয়মের (যেমন, অ্যারে বাউন্ডস (.22.2.5, §7.3)) কেস লেবেল (§2.2.4, §9.4.2), কিছু টেমপ্লেট আর্গুমেন্ট (§25.2) এবং কনস্টেক্সপ্র ব্যবহার করে স্থিরকৃত ঘোষিত হয়েছে)। অন্যান্য ক্ষেত্রে, সংকলন-সময় মূল্যায়ন পারফরম্যান্সের জন্য গুরুত্বপূর্ণ। পারফরম্যান্স ইস্যুগুলির স্বতন্ত্রভাবে, অপরিবর্তনীয়তার ধারণা (অপরিবর্তনীয় রাষ্ট্রের সাথে কোনও বস্তুর) একটি গুরুত্বপূর্ণ নকশা উদ্বেগ (§10.4)।


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

31

উভয় constএবং constexprপরিবর্তনশীল এবং ফাংশন প্রয়োগ করা যেতে পারে। যদিও তারা একে অপরের সাথে সাদৃশ্যপূর্ণ, বাস্তবে এগুলি খুব আলাদা ধারণা con

উভয় constএবং এর constexprঅর্থ হল যে তাদের মানটি আরম্ভের পরে পরিবর্তন করা যাবে না। উদাহরণস্বরূপ:

const int x1=10;
constexpr int x2=10;

x1=20; // ERROR. Variable 'x1' can't be changed.
x2=20; // ERROR. Variable 'x2' can't be changed.

মধ্যে মূল পার্থক্য constএবং constexpr(মূল্যায়ন) সময় যখন তাদের আরম্ভের মান পরিচিত হয়। চলকগুলির মানগুলি constসংকলন সময় এবং রানটাইম উভয় ক্ষেত্রেই constexprমূল্যায়ন করা যায়, সংকলন সময়ে সর্বদা মূল্যায়ন করা হয়। উদাহরণ স্বরূপ:

int temp=rand(); // temp is generated by the the random generator at runtime.

const int x1=10; // OK - known at compile time.
const int x2=temp; // OK - known only at runtime.
constexpr int x3=10; // OK - known at compile time.
constexpr int x4=temp; // ERROR. Compiler can't figure out the value of 'temp' variable at compile time so `constexpr` can't be applied here.

মানটি সংকলনের সময় বা রানটাইমের সময় জানা ছিল কিনা তা জানার মূল সুবিধাটি হ'ল এই বিষয়টি যে কম্পাইল টাইম ধ্রুবকগুলি যখনই সংকলনের সময় ধ্রুবকের প্রয়োজন হয় তখন ব্যবহার করা যায়। উদাহরণস্বরূপ, সি ++ আপনাকে ভেরিয়েবল দৈর্ঘ্যের সাথে সি-অ্যারে নির্দিষ্ট করার অনুমতি দেয় না।

int temp=rand(); // temp is generated by the the random generator at runtime.

int array1[10]; // OK.
int array2[temp]; // ERROR.

সুতরাং এর অর্থ হল:

const int size1=10; // OK - value known at compile time.
const int size2=temp; // OK - value known only at runtime.
constexpr int size3=10; // OK - value known at compile time.


int array3[size1]; // OK - size is known at compile time.
int array4[size2]; // ERROR - size is known only at runtime time.
int array5[size3]; // OK - size is known at compile time.

সুতরাং constভেরিয়েবল নির্ধারণ করতে পারবেন উভয় কম্পাইল সময় ধ্রুবক মত size1যে অ্যারের মাপ এবং নির্দিষ্ট ব্যবহার করা যেতে পারে রানটাইম ধ্রুবক মত size2যে শুধুমাত্র রানটাইম এ পরিচিত হয় এবং অ্যারে মাপ নির্ধারণ করতে ব্যবহার করা যাবে না। অন্যদিকে constexprসর্বদা সংকলনের সময় স্থিরতাগুলি সংজ্ঞায়িত করুন যা অ্যারের আকারগুলি নির্দিষ্ট করতে পারে।

উভয় constএবং constexprফাংশন খুব প্রয়োগ করা যেতে পারে। একটি constফাংশন অবশ্যই একটি সদস্য ফাংশন (পদ্ধতি, অপারেটর) হতে হবে যেখানে constকীওয়ার্ড প্রয়োগের অর্থ এই পদ্ধতিটি তাদের সদস্যের (অ-স্থিতিশীল) ক্ষেত্রের মান পরিবর্তন করতে পারে না। উদাহরণ স্বরূপ.

class test
{
   int x;

   void function1()
   {
      x=100; // OK.
   }

   void function2() const
   {
      x=100; // ERROR. The const methods can't change the values of object fields.
   }
};

constexprএকটি আলাদা ধারণা। এটি একটি ফাংশন (সদস্য বা অ-সদস্য) হিসাবে চিহ্নিত ফাংশন যা সংকলন সময়ে মূল্যায়ন করা যেতে পারে যদি সংকলন সময় ধ্রুবকগুলি তাদের আর্গুমেন্ট হিসাবে পাস করা হয় । উদাহরণস্বরূপ আপনি এটি লিখতে পারেন।

constexpr int func_constexpr(int X, int Y)
{
    return(X*Y);
}

int func(int X, int Y)
{
    return(X*Y);
}

int array1[func_constexpr(10,20)]; // OK - func_constexpr() can be evaluated at compile time.
int array2[func(10,20)]; // ERROR - func() is not a constexpr function.

int array3[func_constexpr(10,rand())]; // ERROR - even though func_constexpr() is the 'constexpr' function, the expression 'constexpr(10,rand())' can't be evaluated at compile time.

উপায় দ্বারা constexprফাংশনগুলি হ'ল নিয়মিত সি ++ ফাংশন যা অ-ধ্রুবক যুক্তিগুলি পাস হয়ে গেলেও বলা যেতে পারে। তবে সেক্ষেত্রে আপনি নন-কনস্টেক্সের মানগুলি পেয়ে যাচ্ছেন।

int value1=func_constexpr(10,rand()); // OK. value1 is non-constexpr value that is evaluated in runtime.
constexpr int value2=func_constexpr(10,rand()); // ERROR. value2 is constexpr and the expression func_constexpr(10,rand()) can't be evaluated at compile time.

constexprএছাড়াও সদস্য ফাংশন (পদ্ধতি), অপারেটর এবং এমনকি কনস্ট্রাকটর প্রয়োগ করা যেতে পারে। এই ক্ষেত্রে.

class test2
{
    static constexpr int function(int value)
    {
        return(value+1);
    }

    void f()
    {
        int x[function(10)];


    }
};

আরও 'পাগল' নমুনা।

class test3
{
    public:

    int value;

    // constexpr const method - can't chanage the values of object fields and can be evaluated at compile time.
    constexpr int getvalue() const
    {
        return(value);
    }

    constexpr test3(int Value)
        : value(Value)
    {
    }
};


constexpr test3 x(100); // OK. Constructor is constexpr.

int array[x.getvalue()]; // OK. x.getvalue() is constexpr and can be evaluated at compile time.

এছাড়াও, সি-তে constexpr intরয়েছে তবে এটি বানানযুক্তconst int
কৌতূহলী

8

@ 0x499602d2 যেমন ইতিমধ্যে নির্দেশ করেছে, constকেবলমাত্র নিশ্চিত করে যে প্রাথমিককরণের পরে কোনও মান পরিবর্তন করা যাবে না যেখানে constexpr(সি ++ 11 তে প্রবর্তিত) চলকটি একটি সংকলন সময় ধ্রুবক হিসাবে গ্যারান্টি দেয়।
নীচের উদাহরণটি বিবেচনা করুন (শিখুনসিপি.কম থেকে)

cout << "Enter your age: ";
int age;
cin >> age;

const int myAge{age};        // works
constexpr int someAge{age};  // error: age can only be resolved at runtime

5

একটি const int varপরিবর্তনশীল রানটাইম এ মান নির্ধারণ করা যাবে এবং একদা এটিকে যে মান সেট করা থাকে, এটা এখন আর পরিবর্তন করা যাবে।

একটি constexpr int varপরিবর্তনশীল কম্পাইল সময়ে রানটাইম এ সেট করা যাবে না, বরং। এবং একবার এটি মান হিসাবে সেট করা হয়, এটি আর পরিবর্তন করা যাবে না।

এখানে একটি দৃ example় উদাহরণ:

int main(int argc, char*argv[]) {
    const int p = argc; 
    // p = 69; // cannot change p because it is a const
    // constexpr int q = argc; // cannot be, bcoz argc cannot be computed at compile time 
    constexpr int r = 2^3; // this works!
    // r = 42; // same as const too, it cannot be changed
}

উপরের স্নিপেট জরিমানা সংকলন করে এবং আমি এগুলিকে মন্তব্য করেছিলাম যার কারণে এটি ত্রুটি ঘটায়।

এখানে যে মূল ধারণাগুলি লক্ষ্য করা যায় তা হ'ল compile timeএবং এর ধারণা run time** know **রানটাইমের সময় পারফরম্যান্সের উন্নতি করতে সংকলন সময়ে যতটা সম্ভব নির্দিষ্ট কিছু জিনিস সম্ভব উদ্দিষ্ট উদ্দেশ্যে নতুন নতুন উদ্ভাবন সি ++ তে প্রবর্তিত হয়েছে ।


3

আমি মনে করি না যে উত্তরগুলির কোনওটিই এটির ঠিক কী পার্শ্ব প্রতিক্রিয়াগুলি, বা প্রকৃতপক্ষে, এটি পরিষ্কার করে দেয়।

constexprএবং constনামস্থান / ফাইল-স্কোপ এ অভিন্ন একটি আক্ষরিক বা অভিব্যক্তি ইনিশিয়ালাইজ হয়; তবে একটি ফাংশন দিয়ে, constকোনও ফাংশন দিয়ে সূচনা করা যেতে পারে তবে constexprএকটি অ-কনসেক্সেক্সপ্র দ্বারা সূচনা করা হয় (একটি ফাংশন যা কনস্টেক্সপ্র বা একটি কনস্টেক্সপ্র এক্সপ্রেশন দিয়ে চিহ্নিত নয়) সংকলক ত্রুটি তৈরি করবে। উভয় constexprএবং constভেরিয়েবলের জন্য স্পষ্টভাবে অভ্যন্তরীণ লিঙ্কেজ (ভাল আসলে, তারা -O1 এবং শক্তিশালী সংকলন করে লিঙ্কিং পর্যায়ে পৌঁছাতে বাঁচতে staticপারে না এবং সংকলকটিকে অভ্যন্তরীণ (স্থানীয়) লিংক প্রতীক নির্গত করতে constবা constexprকখন সংঘবদ্ধ করতে বাধ্য করে না -O1 বা আরও শক্তিশালী; কেবলমাত্র তখনই এটি করা হয় যদি আপনি ভেরিয়েবলের ঠিকানাটি নেন constএবং constexprএটি প্রকাশ না করে অভ্যন্তরীণ প্রতীক হয়ে থাকবেনextern অর্থাতextern constexpr/const int i = 3;ব্যবহার করা প্রয়োজন)। কোনও ফাংশনে, constexprফাংশনটি স্থায়ীভাবে কখনও লিঙ্কিং পর্যায়ে পৌঁছায় না (নির্বিশেষে externবা inlineসংজ্ঞা বা -O0 বা -Of বাছাই constনা করে ), যেখানে কখনও হয় না staticএবং inlineকেবল ও -1 এবং উপরে এটির প্রভাব থাকে। একটি যখন const/ constexprপরিবর্তনশীল একটি দ্বারা ইনিশিয়ালাইজ করা হয় constexprফাংশন, লোড সবসময় কোনো অপ্টিমাইজেশান পতাকা দিয়ে আউট অপ্টিমাইজ করা হয়, কিন্তু এটি আউট অপ্টিমাইজ করা হয় না যদি ফাংশন শুধুমাত্র staticবা inline, অথবা যদি পরিবর্তনশীল একটি নয় const/ constexpr

স্ট্যান্ডার্ড সংকলন (-O0)

#include<iostream>
constexpr int multiply (int x, int y)
{

  return x * y;
}

extern const int val = multiply(10,10);
int main () {
  std::cout << val;
} 

সংকলন

val:
        .long   100  //extra external definition supplied due to extern

main:
        push    rbp
        mov     rbp, rsp
        mov     esi, 100 //substituted in as an immediate
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     eax, 0
        pop     rbp
        ret

__static_initialization_and_destruction_0(int, int):
        . 
        . 
        . 

যাহোক

#include<iostream>
const int multiply (int x, int y)
{

  return x * y;
}

const int val = multiply(10,10); //constexpr is an error
int main () {
  std::cout << val;
}

সংকলন

multiply(int, int):
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], edi
        mov     DWORD PTR [rbp-8], esi
        mov     eax, DWORD PTR [rbp-4]
        imul    eax, DWORD PTR [rbp-8]
        pop     rbp
        ret

main:
        push    rbp
        mov     rbp, rsp
        mov     eax, DWORD PTR val[rip]
        mov     esi, eax
        mov     edi, OFFSET FLAT:_ZSt4cout
        call    std::basic_ostream<char, std::char_traits<char> >::operator<<(int)
        mov     eax, 0
        pop     rbp
        ret

__static_initialization_and_destruction_0(int, int):
        . 
        . 
        . 
        mov     esi, 10
        mov     edi, 10
        call    multiply(int, int)
        mov     DWORD PTR val[rip], eax

এ থেকে পরিষ্কার জানা constexprএর initialisation ঘটায় const/constexprফাইল-স্কোপ পরিবর্তনশীল কম্পাইল সময় এ ঘটতে এবং কোন বিশ্বব্যাপী প্রতীক উত্পাদন করতে, যেহেতু ব্যবহার করছেন না এটা আগে ঘটতে initialisation ঘটায় mainরানটাইম এ।

-অফেষ্ট ব্যবহার করে সংকলন

এমনকি - হালকা লোডটি অপ্টিমাইজ করে না! https://godbolt.org/z/r-mhif , তাই আপনার প্রয়োজন constexpr


constexprconstexprএকই ফলাফলের জন্য অন্যান্য ক্রিয়াকলাপগুলি ভিতরে থেকেও ফাংশনগুলি কল করা যায়। constexprএকটি ফাংশন অন ফাংশন সংকলন সময়ে সম্পন্ন করা যায় না যে কোনও কিছু ব্যবহার প্রতিরোধ করে; উদাহরণস্বরূপ, একটি কল <<উপর অপারেটর std::cout

constexprব্লক স্কোপতে একই আচরণ করে যা এটি একটি ত্রুটি তৈরি করে যদি কোনও অ-কনস্টেক্সপ্রাপ্ত ফাংশন দ্বারা আরম্ভ করা হয়; মানটি অবিলম্বে প্রতিস্থাপিত হয়।

শেষ পর্যন্ত, এর মূল উদ্দেশ্যটি সি এর ইনলাইন ফাংশনের মতো তবে এটি কেবল তখন কার্যকর হয় যখন ফাংশনটি ফাইল-স্কোপ ভেরিয়েবলগুলি সূচনা করতে ব্যবহৃত হয় (যা ফাংশনগুলি সি তে করতে পারে না তবে তারা সি ++ এ করতে পারে কারণ এটি ফাইল- এর গতিশীল সূচনা করার অনুমতি দেয় allows স্কোপ ভেরিয়েবল), ফাংশন ব্যতীত লিঙ্কারে কোনও গ্লোবাল / স্থানীয় প্রতীক রফতানি করতে পারে না, এমনকি সি ব্যবহার করে extern/staticযা আপনি ব্যবহার করতে পারেন inline; ব্লক-স্কোপ ভেরিয়েবল অ্যাসাইনমেন্ট ফাংশনগুলি কেবল constexprসি এবং সি ++ ছাড়াই একটি -O1 অপ্টিমাইজেশন ব্যবহার করে ইনলাইন করা যায় ।


লিঙ্কারে ভাল পয়েন্ট। কম কনটেক্সটার ব্যবহারের জন্য এটি সাধারণভাবে আরও সুরক্ষিত হিসাবে বিবেচনা করা যেতে পারে কারণ এর ফলে কম প্রতীক ফাঁস হয়?
নিল ম্যাকগিল

1
@ নীলম্যাকগিলটি সত্যিকার অর্থে নয় কারণ ইনলাইন এবং স্ট্যাটিক সংশ্লেষকারীকে -O1 বা আরও শক্তিশালী ব্যবহার করে সংকলন করতে গেলে গুণনের জন্য স্থানীয় প্রতীক নির্গমন করবে না। কনটেক্সপ্রইপ হ'ল একমাত্র যা ভেলের জন্য লোডটিকে অনুকূল করে, তবে এটির চেয়ে অন্যটি এটি ফাংশনের আগে স্থির বা ইনলাইন স্থাপনের অনুরূপ। আমি অন্য কিছু ভুলে গেছি। কনটেক্সপ্রইপ হ'ল একমাত্র কীওয়ার্ড যা -O0, স্ট্যাটিক এবং ইনলাইন ডু-তে ফাংশনটির জন্য কোনও চিহ্ন প্রকাশ করে না
লুইস কেলসি

1

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

তবে কনস্টেক্সপ্রের জন্য এটি কিছুটা আলাদা।

কনসেক্সেক্সের জন্য, আপনি একটি সংজ্ঞা দিতে পারেন যা প্রোগ্রাম সংকলনের সময় মূল্যায়ন করা যেতে পারে।

স্পষ্টতই, কনস্টেক্সার হিসাবে ঘোষিত ভেরিয়েবলটি ভবিষ্যতে ঠিক কনস্টের মতো পরিবর্তন করা যায় না।

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