কনস্ট_কাস্ট নিরাপদ?


92

আমি খুব বেশি তথ্য খুঁজে পাচ্ছি না const_cast। আমি কেবলমাত্র তথ্য (স্ট্যাক ওভারফ্লোতে) পেতাম তা হ'ল:

const_cast<>()যোগ করার জন্য / একটি ভেরিয়েবলের অপসারণ const (নেস) (বা উদ্বায়ী-অন্তরীপ) ব্যবহার করা হয়।

এটি আমাকে উদ্বিগ্ন করে তোলে। কোনও const_castকারণে অপ্রত্যাশিত আচরণ ব্যবহার করা যাবে? তা হলে কী?

বিকল্পভাবে, কখন ব্যবহার করা ঠিক হবে const_cast?


4
শীর্ষ উত্তর উপেক্ষা করে এমন কিছু বিষয় যা ভয়ঙ্করভাবে সুস্পষ্ট হতে পারে কিন্তু চিঠিতে উল্লেখ করা হচ্ছে: এটা শুধুমাত্র অনিরাপদ হয়ে যদি আপনি একটি মূলত সংশোধন করার প্রচেষ্টা constবস্তুর একটি অব- মাধ্যমে const-ed রেফারেন্স / পয়েন্টার। যদি এর পরিবর্তে, আপনি কেবলমাত্র const_castদুর্বল (বা আমার ক্ষেত্রে, আলস্যভাবে) নির্দিষ্ট এপিআইয়ের আশেপাশে কাজ করতে যাচ্ছেন যা কেবলমাত্র একটি অ- constরেফারেন্স গ্রহণ করেছে তবে কেবল constপদ্ধতিতে ব্যবহার করা হবে ... তাতে সমস্যা নেই।
আন্ডারস্কোর_ড

উত্তর:


89

const_castআপনি কেবল তখনই নিরাপদ হন যদি আপনি এমন কোনও পরিবর্তনশীল কাস্ট করেন যা মূলত অ-ছিল const। উদাহরণস্বরূপ, যদি আপনার কোনও ফাংশন থাকে যা এটির একটি প্যারামিটার নেয় const char *এবং আপনি কোনও সংশোধনযোগ্য ক্ষেত্রে পাস করেন তবে char *এটি const_castসেই প্যারামিটারটিতে নিরাপদে ফিরে আসে char *এবং এটি সংশোধন করে। তবে, যদি আসল পরিবর্তনশীলটি আসলে ছিল const, তবে ব্যবহারের const_castফলে অনির্ধারিত আচরণ হবে।

void func(const char *param, size_t sz, bool modify)
{
    if(modify)
        strncpy(const_cast<char *>(param), sz, "new string");
    printf("param: %s\n", param);
}

...

char buffer[16];
const char *unmodifiable = "string constant";
func(buffer, sizeof(buffer), true);  // OK
func(unmodifiable, strlen(unmodifiable), false); // OK
func(unmodifiable, strlen(unmodifiable), true);  // UNDEFINED BEHAVIOR

9
এটা সত্য নয়. সি ++ স্ট্যান্ডার্ড। §7.1.​5.1/4 says Except that any class member declared mutable (7.1.1) can be modified, any attempt to modify a const object during its lifetime (3.8) results in undefined behavior কোন প্রচেষ্টা ! মূল পরিবর্তনশীল সম্পর্কে কোনও শব্দ নেই।
আলেক্সি মালিস্তভ

20
@ অ্যালেক্সা: মূল পরিবর্তনশীলটি কী সম্পর্কে নির্দেশিত বা উল্লেখ করা হয় সে সম্পর্কে। আপনি কোনও অ-কনস্ট্যান্ট অবজেক্টের কাছে কনস্ট্যান্ড রেফারেন্স নিতে পারেন, এবং সুতরাং, এটিকে লিখিতযোগ্য রেফারেন্সে কাস্ট করা ভাল-সংজ্ঞায়িত আচরণ হিসাবে রেফার-টু অবজেক্টটি আসলে কনস্ট নয়।
কুকুরছানা

43
@ অ্যালেক্সা মালিস্তভ: নং। একটি "অবজেক্ট" মেমরির (§1.7) দখলকৃত স্টোরেজের আসল অঞ্চলকে বোঝায়। অ-কনস্ট্যান্ট অবজেক্টের কাছে কনস্ট্যান্ড রেফারেন্স নিলে অবজেক্ট কনস্ট হয় না। শুধু একটি const ক্ষেত্রে রেফারেন্স প্যারামিটার ( না একটি const পয়েন্টার প্যারামিটার) কম্পাইলার চুপটি একটি অনুলিপি (§5.2.2 / 5) করার অনুমতি নেই; এখানে হয় না.
অ্যাডাম রোজেনফিল্ড

8
"তবে, যদি মূল ভেরিয়েবলটি বাস্তবে কনস্টেটেড হয় তবে কনস্ট_কাস্ট ব্যবহারের ফলে অপরিজ্ঞাত আচরণের ফলাফল হবে" এই বিবৃতিটি মিথ্যা।
হালকাতা রেস

7
প্রাথমিকভাবে ঘোষণা করা কিছু থেকে অপসারণ করার জন্য এটি ইউবি ব্যবহার করবেন না । কিন্তু এটা হয় UB আসলে যে বস্তুর লিখতে চেষ্টা করুন। যতক্ষণ আপনি কেবল পড়েছেন ততক্ষণ আপনি ভাল আছেন এবং এতে নিজেই ইউবির কারণ হয় না। এটি একটি ভয়াবহ ধারণা, তবে এটি সহজাতভাবে ইউবি নয় not const_castconstconstconst_cast
জেস্পার জুহল

35

আমি দুটি পরিস্থিতি নিয়ে ভাবতে পারি যেখানে কনস্ট_কাস্ট নিরাপদ এবং দরকারী (অন্যান্য বৈধ ক্ষেত্রেও থাকতে পারে)।

একটি যখন আপনার কাছে একটি কনস্ট্যান্ট উদাহরণ, রেফারেন্স বা পয়েন্টার থাকে এবং আপনি কোনও পয়েন্টার বা রেফারেন্সটি পাস করতে চান যা কোনও সংশোধন-সঠিক নয়, তবে আপনি সঠিক অবজেক্টটি পরিবর্তন করবেন না। আপনি পয়েন্টারটি কনস্ট_কাস্ট করতে পারেন এবং এটি এপিআই-তে পাস করতে পারেন, এটি বিশ্বাস করে যে এটি আসলে কিছুই পরিবর্তন করবে না। উদাহরণ স্বরূপ:

void log(char* text);   // Won't change text -- just const-incorrect

void my_func(const std::string& message)
{
    log(const_cast<char*>(&message.c_str()));
}

অন্যটি হ'ল যদি আপনি কোনও পুরানো সংকলক ব্যবহার করছেন যা 'মিউটটেবল' প্রয়োগ করে না এবং আপনি এমন একটি বর্গ তৈরি করতে চান যা লজিক্যাল কনস্ট তবে বিটওয়াইজ কনস্ট নয়। আপনি একটি কনস্ট্যান্ড পদ্ধতিতে 'এটি' কনস্ট_কাস্ট করতে পারেন এবং আপনার শ্রেণীর সদস্যদের সংশোধন করতে পারেন।

class MyClass
{
    char cached_data[10000]; // should be mutable
    bool cache_dirty;        // should also be mutable

  public:

    char getData(int index) const
    {
        if (cache_dirty)
        {
          MyClass* thisptr = const_cast<MyClass*>(this);
          update_cache(thisptr->cached_data);
        }
        return cached_data[index];
    }
};

এই ... এই প্রশ্নের উত্তর বলে মনে হচ্ছে না। তিনি জিজ্ঞাসা করেছিলেন যে const_castএটি
অপরিজ্ঞাত

13
প্রশ্ন থেকে: "বিকল্পভাবে, কনস্ট_কাস্ট ব্যবহার করা কখন ঠিক হবে?"
ফ্রেড লারসন

যেমনটি "কখন এটি অপরিজ্ঞাত হয় না"; কখন এটি কার্যকর হবে তার উদাহরণগুলি তিনি খুঁজছেন না
মাইকেল মরোজেক

আমরা কেবল প্রশ্নের চিঠিগুলিতেই আটকে রাখতে পারি। এর উপর ভিত্তি করে, এর উদাহরণস্বরূপ ব্যবহারের উপস্থাপনা const_castএকটি বৈধ উত্তর। heএকা প্রশ্নই বিষয় হওয়ায় প্রশ্নের কোনও উত্তর নেই ।
ইগেনফিল্ড

24

কনস্ট_কাস্ট সম্পর্কে আপনি কেবলমাত্র এমনই তথ্য খুঁজে পেতে পারতেন তা বিশ্বাস করা আমার পক্ষে কঠিন । দ্বিতীয় গুগল হিট থেকে উদ্ধৃত :

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

তবে, আপনি যদি এমন কোনও বস্তুর দৃ the়তা ফেলে দেন যা স্পষ্টভাবে কনস্ট হিসাবে ঘোষণা করা হয়নি, আপনি নিরাপদে এটি সংশোধন করতে পারেন।


গ্র্রিয়্যাট উত্তর, এই উত্তরটির সাথে এটি একত্রিত করুন এবং আপনি পুরো ছবিটি পাবেন।
bobobobo

হুঁ। আপনার উত্তরের দ্বিতীয় বিবৃতি সম্পর্কে, আমি কি আপনাকে জিজ্ঞাসা করতে পারি যে কোনও জিনিসের জন্য কীভাবে "কনস্ট" নেস রয়েছে যা স্পষ্টভাবে প্রথম স্থানে কনস্ট হিসাবে ঘোষণা করা হয়নি ?.
hAcKnRoCk

@ আইএম, নন-কনস্ট্যান্ট অবজেক্টটিকে কনস্টেবল করার অনেকগুলি উপায় রয়েছে। উদাহরণস্বরূপ, অবজেক্টটি কনস্ট-রেফারেন্স প্যারামিটার হিসাবে পাস করুন। অথবা এটি পয়েন্টার-টু-কনস্টের জন্য নির্ধারণ করুন। বা ব্যবহার const_cast। অথবা এটিতে একটি কনস্ট্যান্ড পদ্ধতি কল করুন।
রব কেনেডি

12

আদম যা বলে। কনস্ট_কাস্ট সহায়ক হতে পারে যেখানে অন্য একটি উদাহরণ:

struct sample {
    T& getT() { 
        return const_cast<T&>(static_cast<const sample*>(this)->getT()); 
    }

    const T& getT() const { 
       /* possibly much code here */
       return t; 
    }

    T t;
};

আমরা প্রথমে ধরণের thisবিন্দুগুলিতে কনস্ট যুক্ত করি, তারপরে আমরা কনস্টের সংস্করণটি কল করি getTএবং তারপরে আমরা রিটার্ন টাইপ থেকে কনটটি সরিয়ে ফেলি, যা বৈধ যেহেতু tঅবশ্যই নন-কনস্ট্যান্ড হতে হবে (অন্যথায়, নন-কনস্ট্যান্ড সংস্করণটি getTথাকতে পারে না) বলা হয়েছে)। আপনি যদি একটি বৃহত ফাংশন বডি পেয়ে থাকেন এবং আপনি অতিরিক্ত কাজগুলি এড়াতে চান তবে এটি খুব কার্যকর হতে পারে।


4
আমি বরং যুক্ত করার দৃ stat়তার জন্য স্ট্যাটিক castালাই ব্যবহার করব: স্ট্যাটিক_কাস্ট <কনট নমুনা *> (এটি)। আমি যখন কনস্ট_কাস্ট পড়ছি তখন এর অর্থ হ'ল কোডটি সম্ভাব্য বিপজ্জনক কিছু করছে, তাই আমি যখন সম্ভব তখন এর ব্যবহার এড়াতে চেষ্টা করি।
এমফাজেকাস

4
ঠিক আছে, প্রথমটি স্ট্যাটিক_কাস্ট হতে পারে, বা এমনকি অন্তর্ভুক্ত_কাস্টও হতে পারে (উত্সাহ দেওয়া)। আমি স্থির কাস্ট ব্যবহার করে এটি ঠিক করব। ধন্যবাদ
জোহানেস স্কাউব -

4
আমি আরও ভাল const_castবা না পিছনে এগিয়ে যান static_castconst_castআপনি যা চান কেবল তা করতে পারে: সিভি-কোয়ালিফায়ার পরিবর্তন করুন। static_castআপনার অভিপ্রায় নয় এমন অপারেশনগুলি 'নিঃশব্দে' সম্পাদন করতে পারে। তবে, প্রথম কাস্ট সম্পূর্ণরূপে নিরাপদ এবং এর static_castচেয়ে নিরাপদ হতে থাকে const_cast। আমি মনে করি এটি এমন একটি পরিস্থিতি যেখানে const_castআপনার অভিপ্রায়টি আরও ভালভাবে static_castযোগাযোগ করে তবে আপনার ক্রিয়াকলাপের সুরক্ষা আরও ভালভাবে যোগাযোগ করে।
ডেভিড স্টোন

10

সংক্ষিপ্ত উত্তর না, এটি নিরাপদ নয়।

দীর্ঘ উত্তরটি হ'ল যদি আপনি এটির ব্যবহার যথেষ্ট জানেন তবে এটি নিরাপদ হওয়া উচিত।

আপনি যখন কাস্টিং করছেন তখন আপনি যা বলছেন তা হ'ল "আমি কম্পাইলারটি কিছু জানি না know" কনস্ট_কাস্টের ক্ষেত্রে, আপনি যা বলছেন তা হ'ল "যদিও এই পদ্ধতিটি অবিচ্ছিন্ন রেফারেন্স বা পয়েন্টার গ্রহণ করে, আমি জানি যে এটি যে পরামিতিটি আমি দিয়েছি তা পরিবর্তন করবে না।"

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


4

আপনি থ্রেড-সুরক্ষার যেকোন সুযোগ নষ্ট করছেন, যদি আপনি এমন কিছু সংশোধন শুরু করেন যা সংকলকটি মনে করেছিল যে এটি কনস্ট্যান্ট ছিল।


4
কি? আপনার যদি অপরিবর্তনীয় (কনস্ট) অবজেক্ট থাকে তবে আপনি এগুলিকে তুচ্ছভাবে থ্রেডগুলির মধ্যে ভাগ করতে পারেন । তাত্ক্ষণিক যে আপনার কোডের একটি টুকরা কনস্ট-নেসকে দূরে সরিয়ে দেয়, আপনি আপনার সমস্ত থ্রেড সুরক্ষা হারাবেন! আমি কেন এটির জন্য ডাউন-মোডেড? দীর্ঘশ্বাস
ফেলুন

9
কোড থ্রেড-নিরাপদ তৈরিতে কনস্ট অবশ্যই কার্যকর একটি সরঞ্জাম, তবে এটি কোনও গ্যারান্টি দেয় না (সংকলন-সময় ধ্রুবকগুলির ক্ষেত্রে বাদে)। দুটি উদাহরণ: একটি কনস্টের অবজেক্টে পারস্পরিক পরিবর্তনশীল সদস্য থাকতে পারে এবং কোনও বস্তুর কাছে একটি কনস্ট পয়েন্টার থাকলে বস্তুটি নিজেই পরিবর্তন হতে পারে কিনা সে সম্পর্কে কিছুই বলে না।
জেমস হপকিন

আমি মনে করি এটি একটি ভাল উত্তর কারণ আমি আপনার শব্দটি ব্যবহারের ক্ষেত্রে সংকলক অপ্টিমাইজারের বিশ্বাস এবং সুরক্ষার অনুভূতি সম্পর্কে ভাবি নি constconstভরসা। const_castসেই বিশ্বাসকে ভেঙে
দিচ্ছে

4
পরিবর্তনীয় এবং থ্রেড-সুরক্ষা সম্পর্কিত: চ্যানেল 9.msdn.com/posts/…
এমএফএইচ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.