অ্যারে ডেটাতে পরিবর্তন রোধ করবেন কীভাবে?


9

বলুন আমার কাছে এমন একটি শ্রেণি রয়েছে যা দেখতে এটি দেখতে (এটি কেবল একটি উদাহরণ):

class A {
    double *ptr;
public:
    A() : ptr( new double[100] ) {}
    A( const A &other ) {
        other.ptr[7] = 15;
    }
    void doNotChangeMyData() const {
        ptr[43] = 14;
    }
    void changeMyData() {
        ptr[43] = 14;
    }
    ~A() { delete[] ptr; }
};

constউভয় কপি কন্সট্রাকটর এবং doNotChangeMyDataফাংশন করতে যাতে ptrপরিবর্তন করা যাবে না; তবে, এই এখনও অ্যারের দ্বারা প্রতি ইঙ্গিত সামগ্রীগুলিকে সংশোধন করার আমাকে দেয় ptr

কেবলমাত্র "সতর্কতা অবলম্বন করা" (বা কাঁচা পয়েন্টার থেকে দূরে ptrপরিবর্তিত হওয়া) এর constউদাহরণস্বরূপ এর অ্যারের সামগ্রীগুলি পরিবর্তন হতে বাধা দেওয়ার কি উপায় আছে ?

আমি জানি আমি এরকম কিছু করতে পারি

void doNotChangeMyData() const {
    const double *const ptr = this->ptr;
    ptr[43] = 14; // then this would fail to compile
}

তবে আমি না ...


1
আপনি একটিstd::vector
idclev 463035818

std::vector::operator[]()সঠিকভাবে মান পরিবর্তন করতে পারেন?
marvinIsSacul

@ প্রাক্তন অজ্ঞাত 666৩৩৮৮১৮ সম্পাদিত প্রশ্ন তাই কোনও বিকল্প নয়;) এটি আরও একটি তাত্ত্বিক প্রশ্ন, তবে হ্যাঁ, এটি কার্যকর vectorহবে।
ক্রিসএমএম

2
@মারভিন আইস্যাকুল নিশ্চিত, তবে std::vector::operator[]() constএকটি constরেফারেন্স দেয়
idclev 463035818

@ ক্রিসম্মে আমি যা প্রত্যাশা করলাম, কেবল ঘরে হাতির উল্লেখ করতে চেয়েছিলাম :)
আইডাক্ল্যাভ 463035818

উত্তর:


7

পয়েন্টারগুলি প্রচার করে না constconstপ্রকারের double*ফলনে যুক্ত হচ্ছে double* const, যার ফলশ্রুতি constহ'ল অমূল্য হবে।

পরিবর্তে, আপনি একটি ব্যবহার করতে পারেন std::vector:

class A {
    std::vector<double> data(100);
public:
    // no explicit copy ctor or dtor
};

একটি std::array:

class A {
    std::array<double, 100> data{};
public:
    // no explicit copy ctor or dtor
};

বা বিল্টিন অ্যারে (প্রস্তাবিত নয়):

class A {
    double data[100] {};
public:
    // no explicit copy ctor or dtor
};

তিনটি বিকল্পের সমস্ত প্রচার করে const

আপনি যদি সত্যিই পয়েন্টার ব্যবহার করতে চান (দৃ strongly়ভাবে প্রস্তাবিত নয়), std::unique_ptrম্যানুয়াল মেমরি পরিচালনা এড়ানোর জন্য কমপক্ষে একটি ব্যবহার করুন । আপনি std::experimental::propagate_constলাইব্রেরির মূলসূত্র 2 টিএস থেকে মোড়ক ব্যবহার করতে পারেন :

class A {
    std::experimental::propagate_const<std::unique_ptr<double[]>> ptr;
public:
    A()
        : ptr{new double[100] {}}
    {
    }
    // manual copy ctor
    A(const A& other)
        : ptr{new double[100]}
    {
        std::copy_n(other.ptr.get(), 100, ptr.get());
    }
    // defaulted move ctor & dtor
    // assignment operator, etc.
    // ...
};

এটি এখনও স্ট্যান্ডার্ডে নেই, তবে অনেক সংকলক এটি সমর্থন করে। অবশ্যই, এই পদ্ধতির সঠিক পাত্রে নিকৃষ্টতর।


অন্তর্নিহিত ডেটা ধরণের পরিবর্তন না করে এটি করার চেষ্টা করা, কোনও কিছুর চেয়ে তাত্ত্বিক প্রশ্ন। যদি সম্ভব না হয়, তবে আমি এটি সম্ভব হিসাবে গ্রহণ করব।
ক্রিসএমএম

@ ক্রিসম্মে আমি একটি পয়েন্টার সমাধান সহ উত্তরটি আপডেট করেছি। তবে কেন :)
এলএফ

"কেন" উত্তর দেওয়া শক্ত, আরও কৌতূহল। "বিল্ট-ইন অ্যারে" বা std::arrayকাজ করবেন না, সংকলনের সময় আপনি যদি আকারটি না জানেন। vectorওভারহেড যুক্ত; unique_ptrওভারহেড যোগ করে না তবে যদি পয়েন্টারটি ভাগ করে নেওয়া প্রয়োজন তবে আপনার প্রয়োজন shared_ptrযা ওভারহেড যুক্ত করে। আমার মনে হয় না ভিএস বর্তমানে সমর্থন করে propagate_const(কমপক্ষে সিপ্রেফারেন্স দ্বারা উল্লিখিত শিরোলেখ ফাইলটি উপস্থিত নেই /std:c++latest) :(
ক্রিসম্মে

1
@ ক্রিসিএমএমের ওভারহেডটি vectorপ্রায়শই টিবিএইচকে অত্যধিক পরিমাণে বিবেচনা করা হয়, বিশেষত ম্যানুয়াল মেমরি পরিচালনার প্রচেষ্টার তুলনায়। এছাড়াও, আপনি যদি পয়েন্টারগুলিকে ম্যানুয়ালি ভাগ করেন তবে আপনাকে একটি রেফারেন্স গণনাটি ব্যবহার করতে হবে, সুতরাং ওভারহেড অদ্ভুত নয় shared_ptr। আমি জানতাম না যে ভিএস propagate_constএখনও সমর্থন করে না (জিসিসি এবং কলং দুজনেই এটি আইআইআরসি সমর্থন করে) তবে অনুমান অনুসারে আমাদের নিজস্ব রোল আউট করা কঠিন নয়।
এলএফ

আমি সম্মত হয়েছি যে ওভারহেডটি ন্যূনতম, তবে কর্মক্ষমতা সমালোচনামূলক (স্মৃতি ও সময়) গুরুত্বপূর্ণ হলে কাঁচা পয়েন্টার ব্যবহার করার কারণ রয়েছে। আমি মাঝে মাঝে vectorএর বিষয়বস্তুগুলি গ্রহণ করে .data()বা এর &vec[0]পরিবর্তে সরাসরি কাজ করি work ভাগ করা ক্ষেত্রে, আমার প্রায়শই পয়েন্টারের এক মালিক থাকে যা তৈরি করে এবং মুছে ফেলে, তবে অন্যান্য শ্রেণি ডেটা ভাগ করে।
ক্রিসএমএম
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.