কনস্টের আগে নাকি কনস্টের পরে?


145

শুরু করার জন্য আপনি সম্ভবত জানেন যে constকোনও একটি অবজেক্টের ডেটা বা পয়েন্টারটি পরিবর্তনযোগ্য নয় বা উভয়ই তৈরি করতে ব্যবহার করা যেতে পারে।

const Object* obj; // can't change data
Object* const obj; // can't change pointer
const Object* const obj; // can't change data or pointer

তবে আপনি সিনট্যাক্সটিও ব্যবহার করতে পারেন:

Object const *obj; // same as const Object* obj;

কেবলমাত্র জিনিসটি মনে হচ্ছে আপনি constকীওয়ার্ডটি রেখেছেন তারার পাশের দিকটি । ব্যক্তিগতভাবে আমি constটাইপের বামে রাখার জন্য এটির তথ্য নির্দিষ্ট করতে পছন্দ করি না কারণ এটি আমার বাম থেকে ডান মানসিকতায় আরও ভাল পড়তে পারে তবে কোন বাক্য গঠনটি প্রথম এসেছিল?

আরও গুরুত্বপূর্ণ বিষয় হল কেন constডেটা নির্দিষ্ট করার দুটি সঠিক উপায় আছে এবং কোন পরিস্থিতিতে আপনি যদি অপরটির চেয়ে বেশি পছন্দ করেন বা প্রয়োজন?

সম্পাদনা:

সুতরাং এটি মনে হচ্ছে এটি একটি স্বেচ্ছাসেবী সিদ্ধান্ত ছিল যখন আমার জন্মের অনেক আগে কম্পাইলাররা কীভাবে বিষয়গুলি ব্যাখ্যা করতে হবে তার মানক খসড়া করা হয়েছিল। যেহেতু constকীওয়ার্ডের বাম দিকে যা প্রয়োগ করা হয় (ডিফল্ট অনুসারে?) আমার ধারণা তারা আবিষ্কার করেছেন যে কীওয়ার্ড প্রয়োগ করতে "শর্টকাট" যুক্ত করতে এবং কোনওভাবেই ঘোষণাপত্র পরিবর্তনের মতো সময় পরিবর্তন না হওয়া পর্যন্ত অন্যান্য উপায়ে বাছাইপর্ব টাইপ করার কোনও ক্ষতি হয়নি। * বা & কে পার্সিং করা হচ্ছে

এটি সিতেও কি তখন আমি ধরে নিচ্ছি?


9
ম্যাক্রোগুলিতে সর্বদা টাইপের const পরে যুক্ত করুন, উদাহরণস্বরূপ #define MAKE_CONST(T) T constপরিবর্তে #define MAKE_CONST(T) const Tযা MAKE_CONST(int *)সঠিকভাবে int * constপরিবর্তে প্রসারিত হবে const int *
jotik

6
এই দুটি স্টাইল আমি "পূর্ব কনস্ট" এবং "ওয়েস্ট কনস্ট" হিসাবে উল্লেখ করেছি।
টম অ্যান্ডারসন

13
@ টমএন্ডারসন তবে সত্যই এটি "পূর্ব কনস্ট" এবং "কনস্ট ওয়েস্ট" হওয়া উচিত।
ওয়াইএসসি

উত্তর:


96

কেন constডেটা নির্দিষ্ট করার দুটি সঠিক উপায় আছে এবং কোন পরিস্থিতিতে আপনি যদি অপরটির চেয়ে বেশি পছন্দ করেন বা তার প্রয়োজন পড়েন?

মূলত, constএকটি নক্ষত্রের পূর্বে নির্দিষ্টকরণকারীর মধ্যে অবস্থানের বিষয়টি গুরুত্বপূর্ণ না কারণ সি ব্যাকরণটি কর্নিগান এবং রিচি দ্বারা সেভাবে সংজ্ঞায়িত করা হয়েছিল।

ব্যাকরণটিকে তারা এভাবে সংজ্ঞায়িত করার কারণটি সম্ভবত ছিল যে তাদের সি সংকলক বাম থেকে ডান থেকে ইনপুটকে পার্স করে এবং প্রতিটি টোকনটি যেমনটি গ্রাস করে ততক্ষণ শেষ করে। গ্রাসকারী *টোকেন একটি পয়েন্টার টাইপ বর্তমান ঘোষণার রাষ্ট্র পরিবর্তন। constপরে মুখোমুখি হওয়া *মানে constপয়েন্টার ঘোষণায় যোগ্যতা প্রয়োগ করা হয়; এর আগে এটির মুখোমুখি হওয়া বাছাই *করা উপাত্তগুলিতে যোগ্যতার প্রয়োগ করা হয়।

constটাইপ স্পেসিফায়ারের আগে বা পরে কোয়ালিফায়ার প্রদর্শিত হলে শব্দার্থক অর্থ পরিবর্তিত হয় না , এটি কোনওভাবেই গৃহীত হয়।

ফাংশন পয়েন্টারগুলি ঘোষণা করার সময় একই ধরণের কেস দেখা দেয়, যেখানে:

  • void * function1(void)একটি ফাংশন ঘোষণা করে যা ফিরে আসে void *,

  • void (* function2)(void)ফাংশনটিতে একটি ফাংশন পয়েন্টার ঘোষণা করে যা প্রত্যাবর্তন করে void

আবার লক্ষ্য করার বিষয়টি হল ভাষাটির বাক্য গঠনটি বাম থেকে ডান পার্সারকে সমর্থন করে।


7
কার্নিগান বইটি সহ-রচনা করেছিলেন তবে সি, কেবল রিচি-এর ডিজাইনে জড়িত ছিলেন না।
টম জিচ

8
কোনটি কখন তা মনে করতে পারিনি। আপনার ব্যাখ্যার জন্য ধন্যবাদ অবশেষে এটি স্মরণ করার জন্য আমার কাছে মিনিটেকনিক রয়েছে। ধন্যবাদ! *সংকলক পার্সার জেনে না নেওয়ার আগে এটি পয়েন্টার হিসাবে এটি ডাটা মানের জন্য কনস্ট। * এর পরে এটি ধ্রুবক পয়েন্টার সম্পর্কিত। উজ্জ্বল। এবং পরিশেষে এটি ব্যাখ্যা করে যে কেন আমি const charপাশাপাশি করতে পারি char const
ভিট বার্নাটিক

2
কেন এটি এইভাবে করা হয়েছিল তা অনুমান করা আমার কাছে বরং দুর্বল / স্ব-বিরোধী বলে মনে হয়। এটি হ'ল, যদি আমি কোনও ভাষা সংজ্ঞায়িত করছিলাম এবং একটি সংকলক লিখছিলাম এবং আমি এটিকে সহজ এবং "বাম থেকে ডান থেকে ইনপুট পার্স করে রাখতে এবং প্রতিটি টোকনটি এটি ব্যবহার করে প্রক্রিয়াজাতকরণ শেষ করতে চাই", আপনি বলেছেন, এটি আমার কাছে মনে হয় আমার constএটির যোগ্যতাযুক্ত জিনিসটির পরে সর্বদা আগমন করা প্রয়োজন ... ঠিক তাই আমি কনসটি গ্রাস করার পরে অবিলম্বে কনস্টের প্রক্রিয়াজাতকরণ শেষ করতে পারতাম। সুতরাং এটি ওয়েস্ট-কনস্টের অনুমতি দেওয়ার চেয়ে নিষিদ্ধ করার পক্ষে যুক্তি বলে মনে হচ্ছে ।
ডন হ্যাচ

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

1
@ ডনহ্যাচ আপনার মনে রাখতে হবে যে, আজকের তুলনামূলকভাবে এবং আমরা ভাল প্রোগ্রামিং ভাষার নকশার সাথে আমাদের পরিচিতির উপর ভিত্তি করে যে অনুমানগুলি করেছি সেগুলি তখনকার ভাষাগুলি ছিল বেশ নতুন জিনিস। এছাড়াও, যদি কারও অনুমোদনযোগ্য বা সীমাবদ্ধ ভাষা থাকে তবে তা মূল্যবান রায়। উদাহরণস্বরূপ, অজগর একটি ++অপারেটর থাকা উচিত ? "বাক্য", ইমো, আমাকে বুঝতে সাহায্য করেছিল যে তারা পারার কারণ ছাড়া অন্য কোনও বিশেষ কারণ ছিল না। তারা আজ একটি ভিন্ন পছন্দ করতে চান / সম্ভবত না।
ragerdl

75

বিধিটি হ'ল:

কনস্ট এটির বাম জিনিসটিতে প্রযোজ্য। যদি বামদিকে কিছু না থাকে তবে এটি এর ডানদিকে প্রয়োগ হয়।

আমি জিনিসটির ডানদিকে কনস্ট ব্যবহার করা পছন্দ করি কারণ এটি "আসল" উপায় কনস্ট সংজ্ঞায়িত হয়।

তবে আমি মনে করি এটি একটি খুব বিষয়গত দৃষ্টিভঙ্গি।


18
আমি এটিকে বাম দিকে রাখা পছন্দ করি তবে আমার মনে হয় ডানদিকে রেখে দেওয়া আরও অর্থবোধ করে। আপনি সাধারণত ডান থেকে বাম থেকে সি ++ তে প্রকারগুলি পড়েন, উদাহরণস্বরূপ Object const *কনস্ট অবজেক্টের পয়েন্টার। আপনি যদি constবাম দিকে রাখেন তবে এটি কোনও অবজেক্টের কাছে পয়েন্টার হিসাবে পড়বে যা কনস্ট, যা সত্যই খুব ভাল প্রবাহিত হয় না।
কলিন ডাউফিনি

1
আমি এই ধারণাটির আওতায় রয়েছি যে বাম দিকের অন্যান্য ধরণের সি ঘোষণাপত্রের সাথে মানব-শৈলীর ধারাবাহিকতার জন্য (কম্পিউটার ভিত্তিতে এটি সঠিক নয় কারণ constএটি কোনও স্টোরেজ শ্রেণি নয়, তবে লোকেরা পার্সার নয়)।
গাইকোসৌর

1
@ আমি এটি বিশ্বাস করি যে এটি কোনও নিয়মের চেয়েও বেশি গাইডলাইন এবং আমি এটি প্রায়শই স্মরণ করার পদ্ধতি হিসাবে শুনেছি যে সংকলকটি এর ব্যাখ্যা করবে কীভাবে ... আমি বুঝতে পারি যে এটি কীভাবে কাজ করে তাই আমি কেবল পিছনের চিন্তার প্রক্রিয়া সম্পর্কে আগ্রহী ছিলাম উভয় উপায়ে এটি সমর্থন করার সিদ্ধান্ত।
এজেজি 85

3
@ হিথহানিকিট এই নিয়মটি বিদ্যমান, তবে এটি আরও খানিকটা
ফাক.

2
@ হিথহান্নিক্যাট: সর্পিল নিয়ম হ'ল প্রথম মন্তব্যকারীর মন্তব্যের বিস্তৃত সংস্করণ "আপনি সাধারণত [সি /] সি ++ তে ডান থেকে বাম থেকে টাইপ পড়েন"। আমি ধারণা করেছিলাম আপনি এটি বিরোধিতা করছেন। যাইহোক, আমি মনে করি আপনি এর পরিবর্তে উত্তরটি নিজেই উল্লেখ করেছেন।
imallett

57

আমি দ্বিতীয় সিনট্যাক্স পছন্দ। এটি ডান থেকে বামে প্রকারের ঘোষণাটি পড়ার দ্বারা 'কী' ধ্রুবক তা ট্র্যাক রাখতে সহায়তা করে:

Object * const obj;        // read right-to-left:  const pointer to Object
Object const * obj;        // read right-to-left:  pointer to const Object
Object const * const obj;  // read right-to-left:  const pointer to const Object

3
যথাযথভাবে। একটি "একটি ধ্রুবক বস্তুর কাছে ধ্রুবক পয়েন্টার" হয় Object const* const, না const const Object*। "কনস্ট্যান্ট" বিশেষ ক্ষেত্রে বাদে বাম দিকে থাকতে পারে না যেখানে এত লোক একেবারে পছন্দ করে। (উপরে স্বাস্থ্য দেখুন।)
cdunn2001

38

একটি ঘোষণায় কীওয়ার্ডগুলির ক্রমটি সমস্ত ঠিক করা হয় না। "এক সত্য ক্রম" এর অনেকগুলি বিকল্প রয়েছে। এটার মত

int long const long unsigned volatile i = 0;

বা এটি হওয়া উচিত

volatile unsigned long long int const i = 0;

??


25
একটি সাধারণ ভেরিয়েবলের সম্পূর্ণ বিভ্রান্তিকর সংজ্ঞা জন্য +1। :)
শিও

@ রুবেনভ - হ্যাঁ, দুর্ভাগ্যক্রমে তারা। ব্যাকরণ শুধু বলে যে একটি এস এর decl-specifier-seqক্রম decl-specifier। ব্যাকরণ দ্বারা প্রদত্ত কোন আদেশ নেই, এবং প্রতিটি কীওয়ার্ডের জন্য উপস্থিতির সংখ্যা কেবল কয়েকটি শব্দার্থ বিধি দ্বারা সীমাবদ্ধ থাকে (আপনার কাছে constদুটি ছাড়া দুটি থাকতে পারে long:-)
বো পারসন

3
@ রুবেনভব - হ্যাঁ, unsignedএকটি প্রকার, একই রকম unsigned intএবং int unsignedunsigned longঅন্য ধরনের, একই হিসাবে unsigned long intএবং int long unsigned। প্যাটার্নটি দেখুন?
বো পারসন

2
@ বো: আমি জগাখিচুড়ি দেখছি, একটি প্যাটার্ন দেখতে তিনটি পেয়েছে ;)। ঠিক আছে, ধন্যবাদ
রুবনেভব

1
আপনি staticশব্দের ঝাঁকুনিতে যুক্ত করতে সক্ষম হতেন তবে সম্প্রতি সংকলকরা অভিযোগ করেছেন যে staticপ্রথমে আসা দরকার।
লাকাতা

8

প্রথম নিয়মটি হ'ল আপনার স্থানীয় কোডিং মানগুলির যে কোনও বিন্যাসের প্রয়োজন। তারপরে: constটাইপিডেফস জড়িত থাকার সময় সামনে রেখে বিভ্রান্তির শেষ হয় না যেমন:

typedef int* IntPtr;
const IntPtr p1;   // same as int* const p1;

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


আমি মনে করি এটি আমাদের এই দোকানে আমাদের তুলনায় স্বচ্ছভাবে সংজ্ঞায়িত মানগুলিতে পয়েন্টারগুলির টাইপডেফগুলি না রাখার কারণটি হাইলাইট করতে পারে ।
এজেজি 85

1
আমার নীতি (যখন আমি একা সিদ্ধান্ত নিতে পাবেন) পরে (সঙ্গতি অনুরোধে জন্য) const করা হয় এবং (অনেক সাধারণভাবে বা typedefs) পয়েন্টার থেকে typedefs ব্যবহার না করার :-)। এবং বিটিডাব্লু, স্ট্রিং :: আইট্রেটার বনাম স্ট্রিং :: কনস্টিটারটি সম্ভবত আপনার সিদ্ধান্তেও সন্নিবেশ করা উচিত। (কেবল জিনিস গুলিয়ে ফেলতে :-)। কোন সঠিক উত্তর নেই।)
জেমস কানজে

আহা হ্যাঁ আমি const std::string::const_iteratorভাল পরিমাপের জন্য আচরণও অন্তর্ভুক্ত করতে পারতাম ;)
এজেজি 85

2
@ জামেসকাঞ্জ - এক মিনিট অপেক্ষা করুন, আমাকে এখানে সাহায্য করুন ... পোস্টের উদাহরণটিতে আমি বিভ্রান্তি দেখতে পাচ্ছি না। const IntPtr p1"ধ্রুবক পূর্ণসংখ্যার পয়েন্টার" (যেমন, "ধ্রুবক পয়েন্টার টু ইন্টিজার") ব্যতীত আর কী বোঝাতে পারে? কীভাবে IntPtrসংজ্ঞায়িত করা হয় তা না জেনেও তাদের সঠিক মনের কেউই p1এটিকে পরিবর্তনযোগ্য বলে মনে করবে না । এবং এই বিষয়টির জন্য, কেউ কেন ভুলভাবে *p1এটি অপরিবর্তনীয় বলে ধরে নেবে ? আরও কি কি, কোথাও কোথাও স্থাপন করা (যেমন, IntPtr const p1) শব্দার্থবিজ্ঞান মোটেও পরিবর্তন করে না।
টড লেহম্যান

3
@ টডলেহম্যান আপনি হয়ত বিভ্রান্তি দেখতে পাবেন না, তবে বেশিরভাগ সি ++ প্রোগ্রামাররা এটি পদ্ধতিগতভাবে করেন এবং এটি ভুল হয়ে যায় (সন্দেহ নেই যে std::vector<T>::const_iteratorএটি যেমন পুনরুক্তিকারী নয়, তবে এটি কী নির্দেশ করছে) things
জেমস কানজে

7

বাম বা ডান উভয়ই গ্রহণযোগ্য বলে historicalতিহাসিক কারণ রয়েছে। স্ট্রস্ট্রুপ 1983 সালের মধ্যে সি ++ তে কনস্টেন্ট যুক্ত করেছিল , তবে এটি সি 98 / সি 90 পর্যন্ত সিতে পরিণত হয়নি।

সি ++ তে সর্বদা ডানদিকে কনস্ট ব্যবহার করার ভাল কারণ রয়েছে। আপনি সর্বত্র সামঞ্জস্য বজায় থাকবেন কারণ কনস্টের সদস্য কার্যাদি এইভাবে ঘোষণা করতে হবে:

int getInt() const;

1
... ঠিক আছে, "ভাল কারণ" ততটা বিশ্বাসযোগ্য নয়, কারণ "কনস্ট" এর জন্য অন্যান্য সম্ভাব্য অবস্থানগুলির অর্থ একই জিনিস নয়। const int& getInt(); int& const getInt();
Maestro

1
@ মেয়েস্ট্রো: আমি প্রস্তাব দিচ্ছি যে int const& getInt();সমান তুলনায় আপনি তুলনামূলক তুলনায় ভাল, const int& getInt();যদিও int& const getInt();আপনি এটির তুলনা করা অপ্রয়োজনীয় (রেফারেন্সগুলি ইতিমধ্যে কনস্ট্যান্ড) আইনী এবং সাধারণত একটি সতর্কতা দেবেন। যাই হোক, একজন সদস্য ফাংশন উপর const পরিবর্তন thisথেকে ফাংশনে পয়েন্টার Foo* constথেকে Foo const* const
নিক ওয়েস্টগেট

constসদস্য ফাংশনটির অর্থ একই জিনিস নয় - বা void set(int)&;কোনও ফাংশনটির জন্য কোনও প্রকার রেফারেন্স?
ডেভিস হেরিং
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.