সি ++ এ নতুন অপারেটরের সাথে মেমরিটি কীভাবে শুরু করবেন?


176

আমি সবে মাত্র সি ++ তে প্রবেশ করতে শুরু করেছি এবং আমি কিছু ভাল অভ্যাস নিতে চাই। যদি আমি কেবল অপারেটরের intসাথে টাইপের একটি অ্যারে বরাদ্দ করেছি, তবে আমি newনিজেই সমস্তগুলি লুপ না করে কীভাবে সেগুলি 0 তে শুরু করতে পারি? আমার কি শুধু ব্যবহার করা উচিত memset? এটি করার কোনও "সি ++" উপায় আছে?


19
আপনি যদি কোনও ভাল সি ++ অভ্যাস বাছাই করতে চান তবে সরাসরি অ্যারে ব্যবহার এড়াতে এবং পরিবর্তে ভেক্টর ব্যবহার করুন। ভেক্টর প্রকার নির্বিশেষে সমস্ত আইটেম আরম্ভ করবে এবং তারপরে আপনাকে মুছে ফেলা [] অপারেটরটি কল করার কথা মনে রাখার দরকার নেই।
ব্রিয়েনেজে

@ ব্রায়ানগেজ: যদি আমার কোনও বাহ্যিক সি ফাংশনে অ্যারে পাস করার দরকার হয় তবে আমি কী কেবল এটি ভেক্টর দিতে পারি?
ড্রিমলাক্স

12
আপনি পাস করতে পারেন &vector[0]
জেমসডলিন

অবশ্যই আপনি সি ফাংশনে অ্যারে পাস করার সময় আপনাকে সাধারণত প্রথম উপাদানটির জন্য পয়েন্টার নির্দিষ্ট করতে হবে, এবং ভেক্টর [0] যেমন @ জামেসডলিন বলেছিলেন, এবং অ্যারের আকার, এই ক্ষেত্রে ভেক্টর.সাইজ () দ্বারা সরবরাহ করা হয়েছে।
ট্রেবার রুড

সম্পর্কিত (অ-অ্যারে প্রকারের জন্য জিজ্ঞাসা করে): স্ট্যাকওভারফ্লো
একনকাগুয়া

উত্তর:


392

এটি সি ++ এর একটি আশ্চর্যজনকভাবে স্বল্প-পরিচিত বৈশিষ্ট্য (এটি প্রমাণ হিসাবে এখনও কেউ উত্তর হিসাবে দেয়নি), তবে এটিতে অ্যারের মান-প্রাথমিককরণের জন্য বিশেষ সিনট্যাক্স রয়েছে:

new int[10]();

মনে রাখবেন যে আপনাকে অবশ্যই খালি বন্ধনী ব্যবহার করতে হবে - আপনি উদাহরণস্বরূপ, ব্যবহার (0)বা অন্য কিছু করতে পারবেন না (এজন্য এটি কেবলমাত্র মান আরম্ভের জন্য কার্যকর)।

এটি স্পষ্টভাবে আইএসও সি ++ 03 5.3.4 [এক্সপ্লোরার নতুন] / 15 দ্বারা অনুমোদিত, যা বলে:

একটি নতুন-এক্সপ্রেশন যা টাইপের একটি অবজেক্ট তৈরি করে Tসেটিকে সেই বস্তুটি আরম্ভ করে:

...

  • নতুন-ইনিশিয়ালাইজারটি যদি ফর্মের হয় ()তবে আইটেমটি মান-প্রাথমিক (8.5) হয়;

এবং এটি যে ধরণের জন্য অনুমোদিত তা সীমাবদ্ধ করে না, তবে (expression-list)ফর্মটি একই বিভাগে আরও বিধি দ্বারা স্পষ্টভাবে সীমাবদ্ধ করা হয়েছে যাতে এটি অ্যারে প্রকারগুলিকে মঞ্জুরি দেয় না।


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

2
@ জেরি: আমাকে অবশ্যই স্বীকার করতে হবে যে আমি এখনও জানতাম না (সম্ভবত কারণ যখন আমি স্ট্যান্ডার্ডটি পড়ি, তখন এটি সি ++ 03 ছিল ইতিমধ্যে)। এটি বলেছিল, এটি উল্লেখযোগ্য যে আমি যে সমস্ত বাস্তবায়ন জানি তা এটি সমর্থন করে (আমি এটি অনুমান করি কারণ এটি বাস্তবায়নের পক্ষে এতটা ক্ষুদ্র)।
পাভেল মিনায়েভ

2
হ্যাঁ, এটি প্রয়োগ করা বেশ তুচ্ছ। নতুন হিসাবে হিসাবে, সমস্ত "মান সূচনা" সি ++ 03 তে নতুন ছিল
জেরি কফিন

34
সি ++ 11 আপনি পাশাপাশি অভিন্ন initializtion ব্যবহার করতে পারেন: new int[10] {}। আপনি এর সাথে আরম্ভ করার জন্য new int[10] {1,2,3}
মানগুলিও সরবরাহ

দয়া করে মান-আরম্ভের সাথে ডিফল্ট-ইনিশিয়ালাইজডটিকে বিভ্রান্ত করবেন না: এগুলি উভয়ই স্পষ্টভাবে স্ট্যান্ডার্ডে সংজ্ঞায়িত করা হয় এবং এটি বিভিন্ন আরম্ভ হয়।
উত্সাহক

25

ধরে নিই যে আপনি সত্যই কোনও অ্যারে চান, স্ট্যান্ড :: ভেক্টর নয়, "সি ++ উপায়" এটি হবে

#include <algorithm> 

int* array = new int[n]; // Assuming "n" is a pre-existing variable

std::fill_n(array, n, 0); 

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


কোনও ফাংশনের নীচে লুপটি প্রয়োগ করা হয়েছে কিনা তাতে আমার আপত্তি নেই, আমি কেবল জানতে চেয়েছিলাম যে আমাকে নিজের মতো লুপটি প্রয়োগ করতে হবে কিনা। বখশিশের জন্য ধন্যবাদ.
ড্রিমলাক্স

4
আপনি অবাক হতে পারেন। আমি ছিলাম. আমার এসটিএলে (উভয় জিসিসি এবং ডিনকামওয়াইয়ার) স্টাডি :: অনুলিপিটি আসলে একটি মেমকিতে রূপান্তরিত করে যদি এটি সনাক্ত করে যে এটি বিল্ট ইন টাইপ সহ কল ​​করা হচ্ছে। স্ট্যান্ড :: ফিল_এন মেমসেট ব্যবহার করলে আমি অবাক হব না।
ব্রায়ান নিল

2
নাঃ। সকল সদস্যকে 0 এ সেট করতে 'মান-সূচনা' ব্যবহার করুন
মার্টিন ইয়র্ক

24

অভ্যন্তরীণ ধরণের অ্যারে বরাদ্দ করার জন্য অনেকগুলি পদ্ধতি রয়েছে এবং এই সমস্ত পদ্ধতি সঠিক, যদিও এটি কোনটি বেছে নিতে হবে তা নির্ভর করে ...

লুপে সমস্ত উপাদান ম্যানুয়াল আরম্ভ

int* p = new int[10];
for (int i = 0; i < 10; i++)
{
    p[i] = 0;
}

std::memsetথেকে ফাংশন ব্যবহার<cstring>

int* p = new int[10];
std::memset(p, 0, sizeof(int) * 10);

std::fill_nথেকে অ্যালগরিদম ব্যবহার করে<algorithm>

int* p = new int[10];
std::fill_n(p, 10, 0);

std::vectorধারক ব্যবহার

std::vector<int> v(10); // elements zero'ed

যদি সি ++ 0 এক্স উপলব্ধ থাকে তবে আরম্ভকারী তালিকা বৈশিষ্ট্যগুলি ব্যবহার করে

int a[] = { 1, 2, 3 }; // 3-element static size array
vector<int> v = { 1, 2, 3 }; // 3-element array but vector is resizeable in runtime

1
ভেক্টর হওয়া উচিত <int> আপনি যদি পি = নতুন ইনট [10] () যোগ করেন তবে আপনার একটি সম্পূর্ণ তালিকা ছিল।
কার্স্টেন

@ম্লোসকোট, প্রথম ক্ষেত্রে যেখানে আপনি "নতুন" ব্যবহার করে একটি অ্যারে শুরু করেছিলেন, রেফারেন্স দিয়ে কীভাবে পাস হবে? যদি আমি int array[SIZE] ={1,2,3,4,5,6,7};স্বরলিপি ব্যবহার করি তবে আমি ব্যবহার void rotateArray(int (& input)[SIZE], unsigned int k);করতে পারি আমার ফাংশন ঘোষণা, প্রথম সম্মেলনটি ব্যবহার করার সময় কী হবে? যেকোনো পরামর্শ?
আনু

1
উদাহরণস্বরূপ std::memsetভুল হিসাবে আমি ভীত - আপনি দশটি পাস করেছেন, এটি বাইট সংখ্যাটি প্রত্যাশা করে বলে মনে হচ্ছে - en.cppreferences.com/w/cpp/string/byte/memset দেখুন । (আমি মনে করি এটি সুন্দরভাবে দেখায় যে কেন সম্ভব হলে নিম্ন স্তরের
সুমা

@ সুমা গ্রেট ক্যাচ! সংশোধন করা হয়েছে। এটি এক দশক পুরানো বাগের জন্য প্রার্থী বলে মনে হচ্ছে :-) হ্যাঁ, আমি আপনার মন্তব্যের সাথে একমত।
এম্লোসকোট

7

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

তবে যদি আপনি কোনও পিওডি বা এমন কিছু বরাদ্দ করেন যা কোনও অবজেক্টের অবস্থার সূচনা করে এমন কোনও কনস্ট্রাক্টর না রাখেন তবে আপনি মেমরি বরাদ্দ করতে পারবেন না এবং একটি স্মরণে অপারেটরের সাথে সেই মেমরিটি আরম্ভ করতে পারবেন না। তবে আপনার কাছে বেশ কয়েকটি বিকল্প রয়েছে:

1) পরিবর্তে একটি স্ট্যাক ভেরিয়েবল ব্যবহার করুন। আপনি এক ধাপে বরাদ্দ এবং ডিফল্ট-আরম্ভ করতে পারেন, এর মতো:

int vals[100] = {0};  // first element is a matter of style

2) ব্যবহার memset()। মনে রাখবেন যে আপনি যে অবজেক্টটি বরাদ্দ করছেন তা যদি কোনও পিওডি না হয় তবে এটির স্মরণে রাখা খারাপ ধারণা। একটি নির্দিষ্ট উদাহরণ হ'ল যদি আপনি ভার্চুয়াল ফাংশনগুলির একটি শ্রেণিকে স্মরণ করেন তবে আপনি ভ্যাটবিলটি উড়িয়ে দেবেন এবং আপনার অবজেক্টটিকে অকেজো অবস্থায় রেখে দেবেন।

3) অনেক অপারেটিং সিস্টেমে কল রয়েছে যা আপনি যা চান তা করেন - একটি গাদাতে বরাদ্দ করুন এবং ডেটাটিকে কিছুতে আরম্ভ করুন। একটি উইন্ডোজ উদাহরণ হবেVirtualAlloc()

4) এটি সাধারণত সেরা বিকল্প। নিজেই স্মৃতিটি পরিচালনা করতে এড়িয়ে চলুন। কাঁচা স্মৃতি নিয়ে আপনি যা কিছু করবেন তার জন্য আপনি এসটিএল কনটেইনারগুলি ব্যবহার করতে পারেন, একসাথে সমস্ত বরাদ্দ এবং প্রাথমিককরণ সহ:

std::vector<int> myInts(100, 0);  // creates a vector of 100 ints, all set to zero

6

হ্যা এখানে:

std::vector<int> vec(SIZE, 0);

গতিশীলভাবে বরাদ্দ করা অ্যারের পরিবর্তে কোনও ভেক্টর ব্যবহার করুন। সুবিধাগুলির মধ্যে রয়েছে স্পষ্টভাবে অ্যারে মুছে ফেলার বিষয়ে বিরক্ত করার দরকার নেই (ভেক্টর সুযোগের বাইরে চলে গেলে এটি মুছে ফেলা হয়) এবং কোনও ব্যতিক্রম ছোঁড়া হলেও মেমরিটি স্বয়ংক্রিয়ভাবে মুছে ফেলা হয়।

সম্পাদনা করুন: নীচে দেওয়া মন্তব্যগুলি পড়তে বিরক্ত করে না এমন লোকদের কাছ থেকে চালিত যানবাহনগুলি এড়াতে, আমার আরও স্পষ্ট করে বলা উচিত যে এই উত্তরটি ভেক্টর সর্বদা সঠিক উত্তর বলে বলে না । তবে এটি অ্যারে মুছে ফেলার বিষয়টি নিশ্চিত করে "ম্যানুয়ালি" এর চেয়ে আরও বেশি সি ++ উপায়।

এখন সি ++ ১১ এর সাথে স্ট্যান্ড :: অ্যারেও রয়েছে যা ধ্রুব আকারের অ্যারে মডেল করে (বনাম ভেক্টর যা বৃদ্ধি করতে সক্ষম)। এছাড়াও রয়েছে স্ট্যান্ড :: অনন্য_পিটার যা গতিশীলভাবে বরাদ্দ হওয়া অ্যারে পরিচালনা করে (যা এই প্রশ্নের অন্যান্য উত্তরে উত্তর হিসাবে প্রাথমিকের সাথে মিলিত হতে পারে)। এগুলির মধ্যে হ'ল আইএমএইচও-তে পয়েন্টারটি ম্যানুয়ালি হ্যান্ডেল করার চেয়ে আরও বেশি সি ++ উপায়।


11
এটি সত্যই জিজ্ঞাসা করা প্রশ্নের উত্তর দেয় না।
জন নোয়েলার

1
আমি কি সর্বদা std::vectorগতিশীলভাবে বরাদ্দ করা অ্যারের পরিবর্তে ব্যবহার করব ? কোনও ভেক্টরের উপরে অ্যারে ব্যবহার করার সুবিধা কী এবং এর বিপরীতে?
স্বপ্নের

1
@ জন নোলার: ওপি এটি করার জন্য একটি সি ++ উপায় সম্পর্কে জিজ্ঞাসা করেছিল, আমি বলব যে ভেক্টর এটি করার জন্য সি ++ উপায়। অবশ্যই, আপনি সঠিক বলেছেন যে এমন পরিস্থিতি হতে পারে যা এখনও একটি সরল অ্যারে করার জন্য আহ্বান জানায় এবং অপের পরিস্থিতি না জেনে এটি এক হতে পারে। আমি তবেই অনুমান করব, যেহেতু এটি প্রশংসনীয় বলে মনে হচ্ছে যে ওপি ভেক্টর সম্পর্কে জানে না।
villintehaspam

1
@ ভিলিন্তেহসপ্যাম: যদিও এই সমাধানটি আমার প্রশ্নের উত্তর দেয় না তবে এটি আমি যে পথ অবলম্বন করছি। টাইলার ম্যাকহেনরি আমার প্রশ্নের উত্তর আরও সরাসরি দিয়েছেন এবং বিশেষত এমন লোকদের জন্য সহায়তা করা উচিত যারা whatever যে কারণেই হোক না কেন std::vector। ব্যবহার করতে পারেন না ।
ড্রিমলাক্স

2
@ ভিলিন্তেহ্যাসপাম: না, এটি করা কোনও সি ++ উপায় নয়। এটি জাভা পদ্ধতিতে এটি করা। vectorপ্রসঙ্গ নির্বিশেষে যেকোন জায়গায় স্টিকিংকে বলা হয় "সি ++ তে জাভা কোড লেখা"।
এএনটি

2

std::fillএক উপায়। অঞ্চলটি পূরণ করার জন্য দুটি পুনরাবৃত্তকারী এবং একটি মান নেয়। এটি, বা লুপের জন্য, (আমি মনে করি) আরও সি ​​++ উপায় হবে।

আদিম পূর্ণসংখ্যার ধরণের অ্যারে 0 তে নির্দিষ্ট করে সেট করার জন্য, memsetঠিক আছে, যদিও এটি ভ্রু বাড়াতে পারে। callocকাস্টের কারণে C ++ থেকে ব্যবহার করা কিছুটা অসুবিধে হলেও এটিকেও বিবেচনা করুন ।

আমার অংশ হিসাবে, আমি প্রায় সবসময় একটি লুপ ব্যবহার করি।

(আমি মানুষের উদ্দেশ্যগুলি দ্বিতীয়-অনুমান করতে পছন্দ করি না, তবে এটি সত্য যে std::vector, সমস্ত জিনিসই সমান, ব্যবহারের চেয়ে পছন্দনীয় new[]))


1

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

int myArray[10];
memset( myArray, 0, 10 * sizeof( int ));

আমি বুঝতে পারি যে আমি ব্যবহার করতে পারি memset, তবে আমি নিশ্চিত ছিলাম না যে এই সমস্যাটি দেখার সি ++ উপায় ছিল কিনা।
ড্রিমলাক্স

1
এটি আসলে 'সি ++ উপায়' নয়, তবে এটি আর কোনও কাঁচা অ্যারে নয়।
পিট কির্খাম

1
@gbrandt: যা বলার অর্থ এটি সি বা সি ++ এর মধ্যে খুব একটা ভাল কাজ করে না। এটি বেশিরভাগ মানের জন্য চর বা স্বাক্ষরবিহীন চর হিসাবে কাজ করে। এটি বেশিরভাগ মানের জন্য 0 (কমপক্ষে বেশিরভাগ বাস্তবায়নে) কাজ করে। অন্যথায়, এটি সাধারণত অকেজো।
জেরি কফিন

1
10 * sizeof( *myArray )এর চেয়ে ডকুমেন্টেড এবং চেঞ্জ-প্রুফ 10 * sizeof( int )
কেভিন রেড

1
যাইহোক, ওপিতে একটি কাঁচা অ্যারে রয়েছে এবং মেমসেটটি সেই অ্যারের শূন্যের দ্রুততম এবং সহজতম উপায়।
গ্রেগর ব্র্যান্ড্ট

-1

সাধারণত আইটেমগুলির গতিশীল তালিকার জন্য, আপনি একটি ব্যবহার করেন std::vector

ভবিষ্যতে কোডের ক্ষেত্রটি কতটা পরিবর্তনশীল তা প্রত্যাশা করে তার উপর নির্ভর করে সাধারণত আমি কাঁচা মেমরি গতিশীল বরাদ্দের জন্য মেমসেট বা একটি লুপ ব্যবহার করি।

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