ভেরিয়েবলের উপর কনটেক্সপ্র বনাম বনাম


303

নিম্নলিখিত সংজ্ঞাগুলির মধ্যে কোনও পার্থক্য আছে?

const     double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;

যদি তা না হয় তবে C ++ 11 এ কোন স্টাইলটি পছন্দ করা হচ্ছে?



উভয়ই সংকলন-সময় ধ্রুবক। তবে আপনি প্রথমটির কনস্ট_কাস্ট করতে এবং এটিতে লিখতে পারেন। তবে এটি যে কোনও সংকলক দ্বারা অপ্টিমাইজ করা হবে যেহেতু এটি সংকলন সময়ে ঘটে যেমন "পঠন" প্রভাবিত করে না।
বোনিটা মন্টেরো

উত্তর:


346

আমি বিশ্বাস করি একটি পার্থক্য আছে। আসুন তাদের নামকরণ করুন যাতে আমরা তাদের সম্পর্কে আরও সহজে কথা বলতে পারি:

const     double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;

উভয় PI1এবং PI2ধ্রুবক, যার অর্থ আপনি এগুলি সংশোধন করতে পারবেন না। তবে কেবল PI2 একটি সংকলন-সময় ধ্রুবক। এটা তোলে হইবে কম্পাইল সময়ে সক্রিয়া করা হবে। PI1সংকলন সময় বা রান সময় সূচনা হতে পারে। তদুপরি, কেবল PI2 এমন একটি প্রসঙ্গে ব্যবহার করা যেতে পারে যার জন্য একটি সংকলন-সময় ধ্রুবক প্রয়োজন। উদাহরণ স্বরূপ:

constexpr double PI3 = PI1;  // error

কিন্তু:

constexpr double PI3 = PI2;  // ok

এবং:

static_assert(PI1 == 3.141592653589793, "");  // error

কিন্তু:

static_assert(PI2 == 3.141592653589793, "");  // ok

আপনার কোনটি ব্যবহার করা উচিত? আপনার প্রয়োজন মেলে যা ব্যবহার করুন। আপনি কি নিশ্চিত করতে চান যে আপনার কাছে একটি সংকলিত সময় ধ্রুবক রয়েছে যা প্রসঙ্গে যেগুলি একটি সংকলন-সময় ধ্রুবক প্রয়োজন সেখানে ব্যবহার করা যেতে পারে? আপনি কি রান সময়তে গণনার সাথে এটি আরম্ভ করতে সক্ষম হতে চান? প্রভৃতি


60
তুমি কি নিশ্চিত? কারণ const int N = 10; char a[N];কাজ করে এবং অ্যারে সীমা অবশ্যই সংকলন-সময় ধ্রুবক হতে হবে।
ফ্রেডওভারফ্লো

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

34
@ ফ্রেড ওভারফ্লো: নন-কনস্টের অ্যারে সূচকগুলি প্রায় এক দশক ধরে "কাজ করেছে" (উদাহরণস্বরূপ এর জন্য জি ++ এক্সটেনশন রয়েছে), তবে এর অর্থ এই নয় যে এটি কঠোরভাবে আইনী সি ++ (যদিও আরও সাম্প্রতিক সি বা সি ++ স্ট্যান্ডার্ড এটিকে আইনী করেছে , আমি কোনটি ভুলে গেছেন)। সংকলনের ধ্রুবকগুলির মধ্যে পার্থক্য হিসাবে, টেমপ্লেট প্যারামিটার এবং enumইনিশিয়ালাইজার হিসাবে ব্যবহার হ'ল constএবং constexpr(এবং উভয়ই doubleকোনওভাবেই কাজ করে না) মধ্যে কেবল দুটি উল্লেখযোগ্য পার্থক্য ।
দামন

17
5.19 ধাপের এক্সপ্রেশন 4 এর অনুচ্ছেদে [expr.const] এছাড়াও একটি (অ-আদর্শিক) নোট যে বিখ্যাতভাবে রূপরেখার যে কোনও বাস্তবায়ন রানটাইমের চেয়ে কমপাইল-টাইমে বিভিন্ন সময়ে (উদাহরণস্বরূপ নির্ভুলতার সাথে সম্মত) করার অনুমতি দেয়। সুতরাং 1 / PI1এবং 1 / PI2বিভিন্ন ফলাফল হতে পারে। আমি মনে করি না এই কারিগরিটি অবশ্য এই উত্তরের পরামর্শের মতো গুরুত্বপূর্ণ।
লুক ড্যান্টন

4
তবে এটি constexpr double PI3 = PI1;আমার জন্য সঠিকভাবে কাজ করে। (এমএসভিএস ২০১৩ সিটিপি)। আমি কি ভুল করছি?
নুপাগাদি

77

এখানে কোনও পার্থক্য নেই, তবে এটি আপনার কাছে কনস্ট্রাক্টর রয়েছে এমন টাইপ করার ক্ষেত্রে গুরুত্বপূর্ণ।

struct S {
    constexpr S(int);
};

const S s0(0);
constexpr S s1(1);

s0এটি একটি ধ্রুবক, তবে এটি সংকলন-সময় আরম্ভ করার প্রতিশ্রুতি দেয় না। s1চিহ্নিত করা হয়েছে constexpr, সুতরাং এটি একটি ধ্রুবক এবং কারণ Sএর নির্মাণকারীকে চিহ্নিত করা হয়েছে constexpr, এটি সংকলন-সময় শুরু করা হবে।

বেশিরভাগ ক্ষেত্রে এটি যখন রানটাইমের সূচনাটি সময়সাপেক্ষ হতে পারে এবং আপনি সেই কাজটি সংকলকটির দিকে ধাক্কা দিতে চান, যেখানে এটি সময়সাপেক্ষও বটে, তবে সংকলিত প্রোগ্রামটির প্রয়োগের সময়টি ধীর করে দেয় না


3
আমি সম্মত হই: আমি যে সিদ্ধান্তে পৌঁছেছি তা হ'ল constexprবস্তুর সংকলন-সময় গণনা অসম্ভব হয়ে উঠলে এটি রোগ নির্ণয়ের দিকে নিয়ে যায়। কম স্পষ্টত কি ধরণের পরামিতি প্রত্যাশা একটি ফাংশন সংকলন সময়ে সঞ্চালিত হতে পারে কিনা প্যারামিটার হিসাবে ঘোষিত করা উচিত constএবং না constexpr: যেমন, constexpr int foo(S)আমি কল করলে সংকলন সময়ে কার্যকর করা হবে foo(s0)?
ম্যাথিউ এম।

4
@ ম্যাথিউইউএম: foo(s0)সংকলন-সময়ে মৃত্যুদন্ড কার্যকর করা হবে কিনা তা নিয়ে আমার সন্দেহ , তবে আপনি কখনই জানেন না: একটি সংকলককে এই ধরনের অপ্টিমাইজেশন করার অনুমতি দেওয়া হয়েছে। অবশ্যই, জিসিসি 4.7.2 বা ঝাঁকুনি না 3.2 আমাকে সংকলন করতে দেয়constexpr a = foo(s0);
রিচি

50

কনসেক্সেক্স এমন একটি মান নির্দেশ করে যা সংকলনের সময় ধ্রুবক এবং পরিচিত।
কনস্ট একটি মানকে নির্দেশ করে যা কেবল ধ্রুবক; সংকলনের সময় জানতে বাধ্যতামূলক নয়।

int sz;
constexpr auto arraySize1 = sz;    // error! sz's value unknown at compilation
std::array<int, sz> data1;         // error! same problem

constexpr auto arraySize2 = 10;    // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr

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

int sz;
const auto arraySize = sz;       // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation

সমস্ত কনটেক্সট্রপ অবজেক্ট কনস্ট, তবে সমস্ত কনস্টেক্স প্রজেক্ট কনস্টেক্সপ্র নয়।

আপনি যদি কম্পাইলারদের গ্যারান্টি দিতে চান যে কোনও ভেরিয়েবলের একটি মান রয়েছে যা সংকলন-সময় ধ্রুবকগুলির প্রয়োজনে প্রসঙ্গে ব্যবহার করা যেতে পারে, তবে পৌঁছানোর সরঞ্জামটি কনটেক্সট্রপ, কনস্টেক্সার নয়।


2
আমি আপনার ব্যাখ্যাটি খুব পছন্দ করেছি .c
ময়ুখ সরকার

1
@MayukhSarkar কেবলমাত্র গুগল সি ++ কেন constexpr যেমন stackoverflow.com/questions/4748083/...
underscore_d

18

একটি কনটেক্সপ্রস সিম্বলিক ধ্রুবককে অবশ্যই একটি মান দিতে হবে যা সংকলনের সময় জ্ঞাত। উদাহরণ স্বরূপ:

constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    constexpr int c2 = n+7;   // Error: we don’t know the value of c2
    // ...
}

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

constexpr int max = 100; 
void use(int n)
{
    constexpr int c1 = max+7; // OK: c1 is 107
    const int c2 = n+7; // OK, but don’t try to change the value of c2
    // ...
    c2 = 7; // error: c2 is a const
}

এই ধরনের " কনস্ট ভেরিয়েবল" দুটি কারণে খুব সাধারণ:

  1. যাতে লোকেরা ব্যবহৃত সি ++ 98, constexpr ছিল না const
  2. তালিকার আইটেম "ভেরিয়েবল" যা ধ্রুবক প্রকাশ নয় (সংকলনের সময় তাদের মান জানা যায় না) তবে আরম্ভের পরে মানগুলি পরিবর্তন করবেন না তারা নিজেরাই ব্যাপকভাবে কার্যকর।

রেফারেন্স: "প্রোগ্রামিং: সি ++ ব্যবহার করে নীতিমালা এবং অনুশীলন" স্ট্রস্ট্রপ দ্বারা


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