আপনি কীভাবে সি ++ এ 'রিলোক' করবেন?


87

আমি reallocসি ++ এ কীভাবে পারি ? এটি ভাষা থেকে অনুপস্থিত মনে হয় - আছে newএবং আছে deleteকিন্তু resize!

আমার এটি দরকার কারণ আমার প্রোগ্রামটি আরও ডেটা পড়ার সাথে সাথে এটি ধরে রাখার জন্য আমার বাফারটি পুনরায় প্রকাশ করতে হবে। আমি মনে করি না যে deleteপুরানো পয়েন্টারটি যুক্ত করা এবং newএকটি নতুন, আরও বড়টিকে যুক্ত করা সঠিক বিকল্প।


8
স্ট্রোভস্ট্রুপের এই একটি দীর্ঘ সময়ের পিছনে, দেখতে উত্তর www2.research.att.com/~bs/bs_faq2.html#renew (এটা একটা ভাল শুরু যদি আপনি ক্লাইন এর সি ++ প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী সহ সি ++ এ নতুন নয়।)
dirkgently

9
@ ডিরকজেন্টলি রেফারেন্স করা উত্তরটি এখন: stroustrup.com/bs_faq2.html#renew - এবং ক্লাইনের এফএকিউ এখন সুপার এফকিউ এর
maxschlepzig

উত্তর:


54

ব্যবহার :: এসটিডি :: ভেক্টর!

Type* t = (Type*)malloc(sizeof(Type)*n) 
memset(t, 0, sizeof(Type)*m)

হয়ে যায়

::std::vector<Type> t(n, 0);

তারপর

t = (Type*)realloc(t, sizeof(Type) * n2);

হয়ে যায়

t.resize(n2);

আপনি যদি পয়েন্টারটি ফাংশনে পাস করতে চান তবে পরিবর্তে

Foo(t)

ব্যবহার

Foo(&t[0])

এটি একেবারে সঠিক সি ++ কোড, কারণ ভেক্টর একটি স্মার্ট সি-অ্যারে।


4
মেমসেট লাইনটি মেমসেট হওয়া উচিত নয় (টি, 0, আকারের (টি) * এন) ;? ম এর পরিবর্তে এন?
রাফেল মায়ার

4
হ্যাঁ এটি সত্যই হওয়া উচিতType* t = static_cast<Type*>(malloc(n * sizeof *t));
রায়ান হেইনিং

4
সি ++ 11 এর সাথে এখন একের t.data()পরিবর্তে ব্যবহার করা হবে&t[0]
knedlsepp

4
আপনি কিভাবে এটি মুছে ফেলতে পারেন?
a3MLord

@ a3MLord: আপনার অর্থ কী? এটিকে সুযোগ থেকে বাদ দিন এবং এটি চলে গেছে।
অরবিট

50

সঠিক বিকল্পটি সম্ভবত এমন একটি ধারক ব্যবহার করা উচিত যা আপনার পক্ষে কাজ করে std::vector

newএবং deleteআকার পরিবর্তন করতে পারে না, কারণ তারা প্রদত্ত ধরণের একটি অবজেক্ট ধরে রাখতে পর্যাপ্ত পরিমাণ মেমরি বরাদ্দ করে। প্রদত্ত ধরণের আকার কখনই পরিবর্তন হবে না। আছে new[]এবং delete[]কিন্তু কমই কখনও তাদের ব্যবহার করার জন্য একটি কারণ আছে।

কি reallocসি আছে শুধু একটি হতে পারে malloc, memcpyএবং freeযদিও মেমরির পরিচালকদের যদি পর্যাপ্ত সংলগ্ন মেমরি মুক্ত উপলব্ধ কিছু চালাক না করার অনুমতি দেওয়া হয়, যাহাই হউক না কেন।


6
@ বোড্যাসিডো: ক্রমবর্ধমান বাফার বাস্তবায়ন করবেন না, কেবল ব্যবহার করুন std::vector- এটি প্রয়োজনের পরে স্বয়ংক্রিয়ভাবে বৃদ্ধি পাবে এবং আপনি ( reserve()) চাইলে মেমরিটিকে প্রাক-বরাদ্দ করতে পারেন ।
শার্পথুথ

4
এসটিডি :: ভেক্টর <টি> ব্যবহার করুন। এটাই তার জন্য। সি ++ এ, নিজেকে নতুন / মুছে ফেলার / নতুন [] / মুছে ফেলা [] নিজেকে ব্যবহার করার কোনও কারণ নেই, যদি না আপনি স্পষ্টভাবে সংস্থান ম্যানেজমেন্ট ক্লাস লেখেন।
কুকুরছানা

4
@ বিড: হ্যাঁ, এটি পারে (সুতরাং std::string, উপায়ে পারেন।)
ফ্রেডওভারফ্লো

4
হ্যাঁ, এটি পারে, কোনও সমস্যা নেই। এমনকি এটি std::stringকরতে পারেন। যাইহোক, আপনার ডেটা রিডিংও সহজসাধ্য হতে পারে এমন একটি সুযোগ রয়েছে। আপনি কিভাবে আপনার তথ্য পড়ছেন?
থমাস

4
এর মতো thevector.resize(previous_size + incoming_size)একটি memcpy(বা অনুরূপ) এর মতো শোনায় &thevector[previous_size]আপনার যা প্রয়োজন তা হল। ভেক্টরের ডেটা "অ্যারের মতো" সংরক্ষণের গ্যারান্টিযুক্ত।
থমাস

38

কনস্ট্রাক্টর এবং ডেস্ট্রাক্টরকে কল করার সম্ভাব্য প্রয়োজনের কারণে সি ++ এ পুনরায় আকার দেওয়া বিশ্রী।

আমি মনে করি না যে সি ++ তে আপনার resize[]সাথে কোনও অপারেটর থাকতে পারে না new[]এবং delete[]এটি এর অনুরূপ কিছু করেছিল:

newbuf = new Type[newsize];
std::copy_n(oldbuf, std::min(oldsize, newsize), newbuf);
delete[] oldbuf;
return newbuf;

স্পষ্টতই oldsizeকোনও গোপন অবস্থান থেকে পুনরুদ্ধার করা হবে, এটি একই সাথে রয়েছে delete[]এবং Typeএটি অপারেন্ডের ধরণ থেকে আসে। resize[]প্রকারটি অনুলিপিযোগ্য নয় যেখানে ব্যর্থ হবে - যা সঠিক, কারণ এই জাতীয় বস্তুগুলি সহজেই স্থানান্তরিত করা যায় না। শেষ অবধি, উপরের কোডটি ডিফল্টরূপে বস্তুগুলিকে নির্ধারিত করার পূর্বে তৈরি করে, যা আপনি প্রকৃত আচরণ হিসাবে চান না।

একটি সম্ভাব্য অপ্টিমাইজেশন রয়েছে যেখানে newsize <= oldsize, সদ্য-প্রত্যয়যুক্ত অ্যারেগুলির "শেষের অতীত" অবজেক্টগুলির জন্য ডেস্ট্রাক্টরদের কল করতে এবং অন্য কিছু না করে। মানটিকে এই অপ্টিমাইজেশনটি প্রয়োজনীয় (কিনা আপনি যখন resize()ভেক্টর হিসাবে) প্রয়োজন, অনুমোদিত তবে অনির্ধারিত, অনুমতিপ্রাপ্ত তবে বাস্তবায়ন-নির্ভর, বা নিষিদ্ধ কিনা তা নির্ধারণ করতে হবে ।

তারপরে আপনার নিজের জিজ্ঞাসা করা প্রশ্নটি হ'ল, "এটি প্রদানের ক্ষেত্রে এটি কি আসলেই কার্যকর হয় vectorএবং এটি একটি পুনরায় আকার-সক্ষম পাত্র সরবরাহের জন্য বিশেষভাবে ডিজাইন করা হয়েছে (স্বতন্ত্র স্মৃতিতে - সেই প্রয়োজনটি C ++ 98 এ বাদ দেওয়া হয় তবে C ++ 03 এ সংশোধন করা হয়েছে) এটি কাজ করার সি ++ পদ্ধতির সাথে অ্যারে তুলনায় আরও ভাল ফিট? "

আমি মনে করি উত্তরটি ব্যাপকভাবে "না" বলে মনে করা হচ্ছে। আপনি যদি সি পদ্ধতিতে পুনরায় আকারে পরিবর্তনযোগ্য বাফার করতে চান তবে ব্যবহার করুন malloc / free / realloc, যা সি ++ এ উপলব্ধ। আপনি যদি সি ++ উপায়ে আকার পরিবর্তনযোগ্য বাফার করতে চান deque, তবে একটি ভেক্টর ব্যবহার করুন (বা , যদি আপনার আসলে স্ট্যাটাসের প্রয়োজন না হয়)। new[]কাঁচা বাফার ব্যবহার করে দুজনকে মিশ্রিত করার চেষ্টা করবেন না , যদি না আপনি ভেক্টরের মতো ধারক ব্যবহার করছেন implementing


0

এখানে একটি স্ট্যান্ড :: মুভের উদাহরণটি একটি রিলোক সহ একটি সাধারণ ভেক্টর বাস্তবায়ন করছে (* 2 প্রতিবার যখন আমরা সীমাটি আঘাত করি তখন)। আমার নীচে থাকা অনুলিপিটির চেয়ে আরও ভাল করার যদি উপায় থাকে তবে দয়া করে আমাকে জানান।

হিসাবে সংকলন:

  g++ -std=c++2a -O2 -Wall -pedantic foo.cpp

কোড:

#include <iostream>
#include <algorithm>

template<class T> class MyVector {
private:
    T *data;
    size_t maxlen;
    size_t currlen;
public:
    MyVector<T> () : data (nullptr), maxlen(0), currlen(0) { }
    MyVector<T> (int maxlen) : data (new T [maxlen]), maxlen(maxlen), currlen(0) { }

    MyVector<T> (const MyVector& o) {
        std::cout << "copy ctor called" << std::endl;
        data = new T [o.maxlen];
        maxlen = o.maxlen;
        currlen = o.currlen;
        std::copy(o.data, o.data + o.maxlen, data);
    }

    MyVector<T> (const MyVector<T>&& o) {
        std::cout << "move ctor called" << std::endl;
        data = o.data;
        maxlen = o.maxlen;
        currlen = o.currlen;
    }

    void push_back (const T& i) {
        if (currlen >= maxlen) {
            maxlen *= 2;
            auto newdata = new T [maxlen];
            std::copy(data, data + currlen, newdata);
            if (data) {
                delete[] data;
            }
            data = newdata;
        }
        data[currlen++] = i;
    }

    friend std::ostream& operator<<(std::ostream &os, const MyVector<T>& o) {
        auto s = o.data;
        auto e = o.data + o.currlen;;
        while (s < e) {
            os << "[" << *s << "]";
            s++;
        }
        return os;
    }
};

int main() {
    auto c = new MyVector<int>(1);
    c->push_back(10);
    c->push_back(11);
}

-7

এরকম কিছু চেষ্টা করুন:

typedef struct Board
{
    string name;
    int size = 0;
};

typedef struct tagRDATA
{
    vector <Board> myBoards(255);

    // Board DataBoard[255];
    int SelectedBoard;

} RUNDATA;

ভেক্টর অভিযোগ করবে। এজন্য অ্যারে, মলোক এবং নতুন এখনও বিদ্যমান।


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