কেন চলক দৈর্ঘ্যের অ্যারেগুলি সি ++ স্ট্যান্ডার্ডের অংশ নয়?


326

আমি গত কয়েক বছরে খুব বেশি সি ব্যবহার করিনি। আজ যখন আমি এই প্রশ্নটি পড়ি তখন আমি কিছু সি বাক্য গঠন নিয়ে এসেছিলাম যার সাথে আমি পরিচিত ছিলাম না।

দৃশ্যত C99 এ নিম্নলিখিত বাক্য গঠন বৈধ:

void foo(int n) {
    int values[n]; //Declare a variable length array
}

এটি দেখতে বেশ কার্যকর বৈশিষ্ট্য বলে মনে হচ্ছে। এটি সি ++ স্ট্যান্ডার্ডে যুক্ত করার বিষয়ে কখনও আলোচনা হয়েছিল এবং যদি তাই হয় তবে কেন এটি বাদ দেওয়া হয়েছিল?

কিছু সম্ভাব্য কারণ:

  • সংকলক বিক্রেতাদের প্রয়োগের জন্য লোমশ
  • স্ট্যান্ডার্ডের অন্য কিছু অংশের সাথে বেমানান
  • কার্যকারিতা অন্যান্য সি ++ নির্মাণের সাথে অনুকরণ করা যায়

সি ++ স্ট্যান্ডার্ড সূচিত করে যে অ্যারের আকার অবশ্যই একটি ধ্রুবক প্রকাশ (8.3.4.1) হওয়া উচিত।

হ্যাঁ, অবশ্যই আমি বুঝতে পারি যে খেলনা উদাহরণে কেউ ব্যবহার করতে পারে std::vector<int> values(m);তবে এটি গাদা থেকে মেমরি বরাদ্দ করে স্ট্যাকটি নয়। এবং যদি আমি একটি বহুমাত্রিক অ্যারে চাই:

void foo(int x, int y, int z) {
    int values[x][y][z]; // Declare a variable length array
}

vectorসংস্করণ চমত্কার কদাকার হয়ে:

void foo(int x, int y, int z) {
    vector< vector< vector<int> > > values( /* Really painful expression here. */);
}

স্লাইস, সারি এবং কলামগুলি সম্ভাব্যভাবে সমস্ত স্মৃতিতে ছড়িয়ে দেওয়া হবে।

comp.std.c++এটিকে আলোচনার দিকে তাকালে এটি স্পষ্ট হয় যে এই প্রশ্নটি তর্কটির উভয় পক্ষের কিছু খুব ভারী ওজনের নাম নিয়ে বেশ বিতর্কিত। এটি অবশ্যই সুস্পষ্ট নয় যে একটি std::vectorসর্বদা একটি ভাল সমাধান।


3
কৌতূহলের বাইরে, কেন এটি স্ট্যাকের উপর বরাদ্দ করা দরকার? আপনি কি হিপ বরাদ্দ কার্য সম্পাদনের সমস্যা নিয়ে আতঙ্কিত?
দিমিত্রি সি

32
@ দিমিত্রি আসলেই নয়, তবে অস্বীকার করার বিষয়টি নেই যে স্তরের বরাদ্দের চেয়ে স্ট্যাকের বরাদ্দ দ্রুত হবে। এবং কিছু ক্ষেত্রে এটি ব্যাপার হতে পারে।
আন্দ্রেয়াস ব্রিন্ক

11
পরিবর্তনশীল দৈর্ঘ্যের অ্যারের মূল সুবিধাটি যে সমস্ত ডেটা একসাথে থাকে তাই আপনি যখন এই অ্যারেটি দিয়ে পুনরাবৃত্তি করেন তখন আপনি একে অপরের পাশে বাইটগুলি পড়েন এবং লেখেন। আপনার ডেটা ক্যাশে আনা হয়েছে এবং সিপিইউ মেমরিটিতে / থেকে বাইটস আনতে এবং না পাঠিয়েই এটিতে কাজ করতে পারে।
কলমারিয়াস

4
পরিবর্তনশীল দৈর্ঘ্যের অ্যারেগুলি স্ট্যাটিক কনস্ট ভেরিয়েবলগুলির সাথে প্রিপ্রোসেসর ধ্রুবকগুলি প্রতিস্থাপন করতেও ব্যবহৃত হতে পারে। সি তেও আপনার কাছে ভিএলএর জন্য অন্য বিকল্প নেই, এবং কখনও কখনও এটি পোর্টেবল সি / সি ++ কোড লিখতে হয় (উভয় সংকলকের সাথে সামঞ্জস্যপূর্ণ)।
ইউরি

2
একপাশে হিসাবে, এটি ঝাঁকুনি ++ উপস্থিত VLAs অনুমতি দেয়।
ব্যবহারকারী 3426763

উত্তর:


204

ইউজননেটে এই লাথি মেরে বন্ধ করার বিষয়ে সম্প্রতি একটি আলোচনা হয়েছিল: সি ++ 0 এক্স-এ কোনও ভিএলএল কেন নেই

আমি সেই সমস্ত লোকদের সাথে একমত হই যেগুলি মনে হয় যে স্ট্যাকের উপরে একটি সম্ভাব্য বড় অ্যারে তৈরি করা, যার মধ্যে সাধারণত খুব কম জায়গা পাওয়া যায়, ভাল না। যুক্তিটি হ'ল, আপনি যদি আকারটি আগেই জানেন তবে আপনি একটি স্ট্যাটিক অ্যারে ব্যবহার করতে পারেন। এবং যদি আপনি আগে থেকে আকারটি না জানেন তবে আপনি অনিরাপদ কোডটি লিখবেন।

সি 99 ভিএলএগুলি অব্যবহৃত উপাদানগুলির জন্য জায়গা নষ্ট না করে বা কন্সট্রাক্টরদের কল না করেই ছোট অ্যারে তৈরি করতে সক্ষম হতে একটি ছোট সুবিধা প্রদান করতে পারে তবে তারা টাইপ সিস্টেমে বরং বড় পরিবর্তনগুলি প্রবর্তন করবে (রানটাইম মানের উপর নির্ভর করে প্রকারগুলি নির্দিষ্ট করতে আপনাকে সক্ষম হতে হবে - এটি newঅপারেটর টাইপ-স্পেসিফায়ার বাদে বর্তমান সি ++ তে এখনও বিদ্যমান নেই , তবে তাদের বিশেষভাবে চিকিত্সা করা হয়, যাতে রানটাইম-নেস newঅপারেটরের সুযোগ থেকে বাঁচতে পারে না )।

আপনি ব্যবহার করতে পারেন std::vector, তবে এটি একরকম নয়, কারণ এটি গতিশীল মেমরি ব্যবহার করে এবং এটি নিজের স্ট্যাক-বরাদ্দকারীকে ব্যবহার করা ঠিক সহজ নয় (প্রান্তিককরণও একটি সমস্যা) এটি একই সমস্যাটিও সমাধান করে না, কারণ একটি ভেক্টর একটি পরিবর্তনযোগ্য ধারক, যেখানে ভিএলএগুলি নির্দিষ্ট আকারের। সি ++ ডায়নামিক এরে প্রস্তাব ভিত্তিক VLA একটি ভাষা বিকল্প হিসাবে একটি লাইব্রেরি ভিত্তিক সমাধান পরিচয় করিয়ে দিতে, উদ্দীষ্ট। তবে যতদূর আমি জানি এটি সি ++ 0x এর অংশ হতে যাচ্ছে না।


22
+1 এবং স্বীকৃত। যদিও একটি মন্তব্য, আমি মনে করি সুরক্ষার যুক্তিটি কিছুটা দুর্বল, কারণ স্ট্যাকের অতিরিক্ত প্রবাহ ঘটানোর আরও অনেক উপায় রয়েছে। সুরক্ষার যুক্তি সেই অবস্থানটি সমর্থন করতে ব্যবহার করা যেতে পারে যে আপনার কখনই পুনরাবৃত্তি ব্যবহার করা উচিত নয় এবং আপনাকে গাদা থেকে সমস্ত বস্তু বরাদ্দ করা উচিত ।
আন্দ্রেয়াস ব্রিন্ক

17
সুতরাং আপনি বলছেন যে স্ট্যাক ওভারফ্লোগুলি সৃষ্টির অন্যান্য উপায় আছে, তাই আমরা তাদের আরও উত্সাহিত করতে পারি?
জাল্ফ

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

10
কারণ (উদাহরণস্বরূপ সি কঠোর টাইপ ম্যাচ ++, VLAs ভাষার স্পেসিফিকেশন সম্ভবত যথেষ্ট আরো সি জন্য জটিল would ++: এছাড়াও যে থ্রেড ম্যাট Austern এর উত্তর তাকান সি একটি বরাদ্দ দেয় T(*)[]একটি থেকে T(*)[N]- সি ++ এ এই দেখানোর অনুমতি নেই, সি যেহেতু ++, "ধরণের সামঞ্জস্যতা" সম্পর্কে জানেন না - এটির জন্য সঠিক মিলগুলি প্রয়োজন), টাইপ প্যারামিটার, ব্যতিক্রম, কন- এবং ডেস্ট্রাক্টর এবং স্টাফ। আমি নিশ্চিত নই যে ভিএলএএস-এর সুবিধাগুলি সত্যিই সেই সমস্ত কাজ পরিশোধ করবে। তবে, আমি বাস্তব জীবনে কখনই ভিএলএগুলি ব্যবহার করি নি, তাই আমি সম্ভবত তাদের জন্য ভাল ব্যবহারের ক্ষেত্রে জানি না।
জোহানেস স্কাউব -

1
@ হেল্পস: সম্ভবত এটির জন্য সবচেয়ে ভাল কি হতে পারে যা কিছুটা আচরণ করে vectorতবে একটি নির্দিষ্ট LIFO ব্যবহারের ধরণ প্রয়োজন এবং প্রতি থ্রেড প্রতি এক বা একাধিক স্ট্যাটিটিক্যালি-বরাদ্দিত বাফারগুলি বজায় রাখে যা সাধারণত থ্রেডের বৃহত্তম মোট বরাদ্দ অনুযায়ী আকারযুক্ত হয় কখনও ব্যবহৃত হয়, তবে যা পরিষ্কারভাবে ছাঁটাই করা যেতে পারে। একটি সাধারণ "বরাদ্দ" সাধারণ ক্ষেত্রে পয়েন্টার অনুলিপি, পয়েন্টার-থেকে-পয়েন্টার বিয়োগ, পূর্ণসংখ্যার তুলনা এবং পয়েন্টার সংযোজন ছাড়া আর কিছুই প্রয়োজন হয় না; ডি-বরাদ্দের জন্য কেবল পয়েন্টার অনুলিপি লাগবে। ভিএলএর চেয়ে বেশি ধীর নয়।
সুপারক্যাট

216

(পটভূমি: আমার সি এবং সি ++ সংকলক প্রয়োগ করার কিছু অভিজ্ঞতা আছে))

সি 99 এর পরিবর্তনশীল দৈর্ঘ্যের অ্যারেগুলি মূলত একটি মিসটপ ছিল। ভিএলএএসকে সমর্থন করার জন্য, সি 99 কে সাধারণ বোধে নিম্নলিখিত ছাড়গুলি দিতে হয়েছিল:

  • sizeof xআর সবসময় একটি সংকলন-সময় ধ্রুবক হয় না; sizeofসংকলকটি কখনও কখনও রানটাইমে একটি এক্সপ্রেশন মূল্যায়ন করতে কোড উত্পন্ন করতে হবে ।

  • দ্বি-মাত্রিক VLAs অনুমতি ( int A[x][y]) ফাংশন যে পরামিতি হিসেবে 2D VLAs নেওয়া প্রকাশক জন্য একটি নতুন বাক্য গঠন প্রয়োজন: void foo(int n, int A[][*])

  • সি ++ বিশ্বে কম গুরুত্বপূর্ণ, তবে এম্বেডড-সিস্টেম প্রোগ্রামারগুলির সি টার্গেট শ্রোতার পক্ষে অত্যন্ত গুরুত্বপূর্ণ, একটি ভিএলএ ঘোষণা করার অর্থ আপনার স্ট্যাকের একটি নির্বিচারে বড় অংশকে ছোপানো । এটি একটি গ্যারান্টিযুক্ত স্ট্যাক-ওভারফ্লো এবং ক্রাশ। (যে কোনও সময় আপনি ঘোষণার int A[n]পরে, আপনি nস্পষ্টতই জোর দিয়ে বলছেন যে আপনার কাছে 2 জিবি ছাড়ার মতো স্ট্যাক রয়েছে After সর্বোপরি, যদি আপনি জানেন তবে " এখানে অবশ্যই 1000 এর চেয়ে কম আছে"), তবে আপনি কেবল ঘোষণা করবেন for এর জন্য int A[1000]32-বিট পূর্ণসংখ্যার nস্থান 1000পরিবর্তন একটি ভর্তি আপনার প্রোগ্রামের আচরণটি কী হওয়া উচিত তা আপনার কোনও ধারণা নেই))

ঠিক আছে, সুতরাং এখন C ++ সম্পর্কে কথা বলা যাক। সি ++-তে, আমাদের মধ্যে "টাইপ সিস্টেম" এবং "ভ্যালু সিস্টেম" এর মধ্যে একই শক্তিশালী পার্থক্য রয়েছে যা সি ৯৯… তবে আমরা সিটিতে যেভাবে নেই তার উপর নির্ভর করতে শুরু করেছি। উদাহরণ স্বরূপ:

template<typename T> struct S { ... };
int A[n];
S<decltype(A)> s;  // equivalently, S<int[n]> s;

যদি nএকটি সংকলন-সময় ধ্রুবক না (যেমন, যদি Aপরিবর্তনশীল পরিবর্তিত ধরণের হয়), তবে পৃথিবীতে কি ধরণের হবে S? হায় S'র টাইপ এছাড়াও শুধুমাত্র রানটাইম এ নির্ধারণ করা?

এই সম্পর্কে কি:

template<typename T> bool myfunc(T& t1, T& t2) { ... };
int A1[n1], A2[n2];
myfunc(A1, A2);

সংকলকটির কিছু তাত্ক্ষণিকতার জন্য কোড উত্পন্ন করতে হবে myfunc। এই কোডটি দেখতে কেমন হবে? A1সংকলনের সময়টির ধরণটি না জানলে আমরা কীভাবে স্ট্যাটিকালি সেই কোডটি তৈরি করতে পারি ?

সবচেয়ে খারাপ, এটি যদি রানটাইমের সময় দেখা দেয় যে n1 != n2তাই !std::is_same<decltype(A1), decltype(A2)>()? সেক্ষেত্রে কলটি myfunc সংকলনও করা উচিত নয় , কারণ টেমপ্লেটের ধরণের কাটা ব্যর্থ হওয়া উচিত! রানটাইমে আমরা কীভাবে সেই আচরণটি অনুকরণ করতে পারি?

মূলত, সি ++ আরও এবং আরও বেশি সিদ্ধান্তকে সংকলন-সময় : টেমপ্লেট কোড তৈরি, constexprফাংশন মূল্যায়ন ইত্যাদির দিকে এগিয়ে যাওয়ার দিকে এগিয়ে চলেছে । এদিকে, C99 রানটাইমের মধ্যে tradition তিহ্যগতভাবে সংকলন-সময় সিদ্ধান্তগুলি (উদাঃ sizeof) চাপতে ব্যস্ত ছিল । এটিকে মনে রেখে, C99- স্টাইলের ভিএলএলএসকে সি ++ তে সংহত করার চেষ্টা করা কোনও প্রচেষ্টা ব্যয় করা কি সত্যিকার অর্থে আসে ?

প্রতিটি অন্যান্য উত্তরদাতা ইতিমধ্যে উল্লেখ করেছেন যে, সি ++ প্রচুর পরিমাণে হিপ-বরাদ্দ প্রক্রিয়া সরবরাহ করে ( std::unique_ptr<int[]> A = new int[n];বা std::vector<int> A(n);স্পষ্টত হওয়া) যখন আপনি সত্যই এই ধারণাটি প্রকাশ করতে চান "আমার কতটা র্যাম দরকার হতে পারে তা আমার কোনও ধারণা নেই।" এবং সি ++ অনিবার্য পরিস্থিতি মোকাবিলার জন্য একটি নিফটি ব্যতিক্রম-হ্যান্ডলিং মডেল সরবরাহ করে যে আপনার যে পরিমাণ র‌্যাম প্রয়োজন তা আপনার পরিমাণের চেয়ে বেশি is তবে আশাকরি এই উত্তরটি আপনাকে কেন C99- স্টাইলের ভিএলএল সি সি ++ এর জন্য উপযুক্ত নয় - এবং সি 99 এর জন্য খুব ভাল ফিটও নয় সে সম্পর্কে একটি ভাল ধারণা দেয় । ;)


বিষয়ে আরও তথ্যের জন্য, N3810 "অ্যারে এক্সটেনশনের বিকল্পগুলি" , ভিএলএএস-এর বজর্ন স্ট্রোস্ট্রপের অক্টোবর ২০১ paper পত্রিকা দেখুন। বার্জার্নের পিওভ আমার থেকে খুব আলাদা; N3810 জিনিসগুলির জন্য ভাল সি ++ ইশ সিনট্যাক্স সন্ধান করতে এবং সি ++ এ কাঁচা অ্যারের ব্যবহারকে নিরুৎসাহিত করার দিকে আরও বেশি জোর দেয় , যেখানে আমি রূপক ও টাইপ সিস্টেমের প্রভাবগুলিতে আরও মনোনিবেশ করেছি। আমি জানি না যে তিনি রূপক / টাইপ সিস্টেমের প্রভাবগুলি সমাধান, দ্রবণযোগ্য বা নিছক উদ্দীপনা বিবেচনা করছেন কিনা।


এই একই পয়েন্টগুলির মধ্যে বেশ কয়েকটিতে হিট একটি ভাল ব্লগ পোস্ট হ'ল "ভেরিয়েবল দৈর্ঘ্যের অ্যারেগুলির আইনী ব্যবহার" (ক্রিস ওয়েলনস, 2019-10-27)।


15
আমি সম্মত ভিএলএগুলি ঠিক ভুল ছিল। আরও অনেক বেশি কার্যকরভাবে প্রয়োগ করা এবং এর চেয়ে বেশি কার্যকর, এর alloca()পরিবর্তে C99 এ মানক করা উচিত ছিল। ভিএলএগুলি হ'ল তখন কি হয় যখন কোনও স্ট্যান্ডার্ড কমিটি অন্যান্য উপায়ের পরিবর্তে বাস্তবায়নের আগে ঝাঁপিয়ে পড়ে।
ম্যাড সায়েন্টিস্ট 11 '21

10
পরিবর্তনশীল-সংশোধিত টাইপ সিস্টেমটি একটি দুর্দান্ত সংযোজন আইএমও এবং আপনার বুলেট পয়েন্টগুলির কোনওটিই সাধারণ জ্ঞান লঙ্ঘন করে না। (1) সি স্ট্যান্ডার্ডটি "সংকলন-সময়" এবং "রান-টাইম" এর মধ্যে পার্থক্য করে না তাই এটি একটি ইস্যু নয়; (২) *optionচ্ছিক, আপনি লিখতে পারেন (এবং হওয়া উচিত) int A[][n]; (3) আপনি কোনও ভিএলএ ঘোষণা না করেই টাইপ সিস্টেমটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ কোনও ফাংশন পরিবর্তনশীল পরিবর্তিত প্রকারের অ্যারে গ্রহণ করতে পারে এবং এটিকে ভিন্ন মাত্রার নন-ভিএলএ 2-ডি অ্যারে দিয়ে ডাকা যেতে পারে। তবে আপনি আপনার পোস্টের পরবর্তী অংশে বৈধ পয়েন্টগুলি তৈরি করেন।
এমএম

3
"ভিএলএর ঘোষণার অর্থ আপনার স্ট্যাকের একটি ইচ্ছামত বৃহত অংশকে ছোপানো This এটি একটি গ্যারান্টিযুক্ত স্ট্যাক-ওভারফ্লো এবং ক্র্যাশ ( মিথ্যা I আমি কোনও স্ট্যাকের ওভারফ্লো ছাড়াই 2GB এর চেয়ে কম স্ট্যাক সহ একটি ভিএলএ প্রোগ্রাম চালিয়েছি
জেফ

3
@ জেফ: nআপনার পরীক্ষার ক্ষেত্রে সর্বাধিক মূল্য কত ছিল এবং আপনার স্ট্যাকের আকার কত ছিল? আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি nআপনার স্ট্যাকের আকারের কমপক্ষে বৃহত্তর একটি মান ইনপুট করার চেষ্টা করুন । (এবং যদি ব্যবহারকারীর পক্ষে nআপনার প্রোগ্রামের মান নিয়ন্ত্রণের কোনও উপায় না থাকে তবে আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি কেবলমাত্র সর্বাধিক মানটি nসরাসরি ঘোষণার মধ্যে প্রচার করুন : int A[1000]আপনাকে যা প্রয়োজন তা ঘোষণা করুন বা কেবল বিপজ্জনক, যখন সর্বাধিক মান nকোনও ছোট সংকলন-সময় ধ্রুবক দ্বারা আবদ্ধ হয় না))
কুইকসপ্লসোন

2
যেহেতু এই জাতীয় সংজ্ঞা ব্যবহার করে বরাদ্দ () বরাদ্দ করা যায় এটি সংজ্ঞায়িত সত্য যে বরাদ্দ () কোনও প্ল্যাটফর্মে সংকলক স্ট্যান্ডার্ড ফাংশন হিসাবে প্রয়োগ করা যেতে পারে। সংকলক বরাদ্দের প্রথম উদাহরণটি সনাক্ত করতে পারে না এর কোনও কারণ নেই () এবং কোডে এম্বেড করার জন্য বিভিন্ন ধরণের চিহ্ন এবং প্রকাশের ব্যবস্থা করতে পারে এবং কোনও সংকলক হিপ ব্যবহার করে বরাদ্দ () বরাদ্দ করতে পারে না এমন কোনও কারণ নেই এটি স্ট্যাক দিয়ে করা যাবে না। হার্ড / নন-পোর্টেবল যা হ'ল তা হল একটি সি কম্পাইলারের উপরে বরাদ্দ () প্রয়োগ করা হয়েছে , যাতে এটি সংকলক এবং অপারেটিং সিস্টেমের বিস্তৃত অ্যারে জুড়ে কাজ করে।
ম্যাড সায়েন্টিস্ট

26

রানটাইমের সময় স্ট্যাকের মেমরি বরাদ্দ করতে আপনি সর্বদা বরাদ্দ () ব্যবহার করতে পারেন, আপনি যদি চান:

void foo (int n)
{
    int *values = (int *)alloca(sizeof(int) * n);
}

স্ট্যাকের জন্য বরাদ্দ হওয়ার অর্থ হ'ল স্ট্যাকটি যখন খুলে যায় তখন তা স্বয়ংক্রিয়ভাবে মুক্তি পাবে।

তাত্ক্ষণিক দ্রষ্টব্য: বরাদ্দ (3) এর জন্য ম্যাক ওএস এক্স ম্যান পৃষ্ঠাতে যেমন উল্লেখ করা হয়েছে, "বরাদ্দ () ফাংশনটি মেশিন এবং সংকলক নির্ভর; এটির ব্যবহারটি ডিস-ক্রেজেড।" ঠিক যেমন তুমি জানো.


4
এছাড়াও, বরাদ্দ () এর স্কোপটি সম্পূর্ণ ফাংশন, কেবল ভেরিয়েবলযুক্ত কোডের ব্লক নয়। সুতরাং এটি একটি লুপের ভিতরে ব্যবহার করা এটি ক্রমাগত স্ট্যাক বাড়িয়ে তুলবে। একটি ভিএলএর সমস্যা নেই।
সাশোলাম

3
যাইহোক, ভিএলএলগুলি এনকোলেসিং ব্লকের সুযোগ রয়েছে এর অর্থ তারা পুরো ফাংশনের সুযোগ সহ বরাদ্দ () এর চেয়ে উল্লেখযোগ্যভাবে কম দরকারী। বিবেচনা করুন: if (!p) { p = alloca(strlen(foo)+1); strcpy(p, foo); } এটি ভিএলএগুলি দিয়ে করা যায় না, অবিকল তাদের ব্লকের সুযোগের কারণে।
ম্যাড সায়েন্টিস্ট

1
এটি ওপির কেন প্রশ্নের উত্তর দেয় না । তদুপরি, এটি একটি Cঅনুরূপ সমাধান, এবং সত্যই- C++আইশ নয়।
অ্যাড্রিয়ান ডাব্লু

13

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

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


12

এমন পরিস্থিতি রয়েছে যেখানে সঞ্চালিত ক্রিয়াকলাপের তুলনায় হিপ মেমরি বরাদ্দ করা খুব ব্যয়বহুল। একটি উদাহরণ ম্যাট্রিক্স গণিত। আপনি যদি ছোট ম্যাট্রিকের সাথে কাজ করেন তবে 5 থেকে 10 টি উপাদান বলুন এবং প্রচলিত পাটিগণিত করুন ম্যালোক ওভারহেডটি সত্যই তাৎপর্যযুক্ত হবে। একই সময়ে আকারকে একটি সংকলন ধ্রুবক করে তোলা খুব অপচয় এবং জটিল নয় বলে মনে হয়।

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


12

দেখে মনে হচ্ছে এটি সি ++ ১৪ এ উপলব্ধ হবে:

https://en.wikipedia.org/wiki/C%2B%2B14#Runtime-sized_one_dimensional_arrays

আপডেট: এটি এটিকে C ++ 14 এ পরিণত করেনি।


মজাদার. ডাব্লামিক অ্যারে এর অধীনে হার্ব সটার এটিকে এখানে আলোচনা করেছেন : isocpp.org/blog/2013/04/trip-report-iso-c-spring-2013- মিটিং (এটি উইকিপিডিয়া তথ্যের জন্য রেফারেন্স)
ডিফল্ট

1
"চালান টাইম আকারের বিন্যাস এবং dynarray এরে এক্সটেনশানগুলি প্রযুক্তিগত স্পেসিফিকেশন স্থানান্তরিত করা হয়েছে" উইকিপিডিয়ায় 78.86.152.103 লিখেছেন 18 জানুয়ারি 2014 উপর: en.wikipedia.org/w/...
strager

10
উইকিপিডিয়া কোনও আদর্শিক রেফারেন্স নয় :) এই প্রস্তাবটি এটি C ++ 14 এ রূপ দেয়নি।
এমএম

2
@ ভিক্টরসেহর: এই আর্ট সি ++ 17 এর অবস্থা কী?
einpoklum

@ আইনপোকলুম কোনও ধারণা নেই, বুস্ট ব্যবহার করুন :: ধারক :: স্ট্যাটিক_ভেক্টর
ভিক্টর সেহর

7

এটি সি ++ / 1 এক্স অন্তর্ভুক্ত করার জন্য বিবেচিত হয়েছিল, তবে বাদ দেওয়া হয়েছিল (এটি আমি যা বলেছিলাম তার একটি সংশোধন)।

এটি ইতিমধ্যে সি ++ তে কম কার্যকর হবে কারণ আমাদের ইতিমধ্যে std::vectorএই ভূমিকাটি পূরণ করতে হবে।


42
না, আমরা না, std :: ভেক্টর স্ট্যাকের উপর ডেটা বরাদ্দ করে না। :)
কোস

7
"স্ট্যাক" একটি বাস্তবায়ন বিশদ; সংকলক এতক্ষণ যে কোনও জায়গা থেকে স্মৃতি বরাদ্দ করতে পারে যতক্ষণ অবজেক্টের আজীবন সম্পর্কে গ্যারান্টি পূরণ হয়।
এমএম

1
@ মিমি: যথেষ্ট ন্যায্য, তবে বাস্তবে আমরা এখনও std::vectorবলার পরিবর্তে ব্যবহার করতে পারি না alloca()
einpoklum

আপনার প্রোগ্রামটির সঠিক আউটপুট পাওয়ার ক্ষেত্রে @ আইনপোকলুম, আপনি পারেন। পারফরম্যান্স একটি মানের বাস্তবায়ন সমস্যা
এমএম

1
@ এমএম মানের-বাস্তবায়ন পোর্টেবল নয়। এবং যদি আপনার পারফরম্যান্সের প্রয়োজন না হয় তবে আপনি প্রথমে সি ++ ব্যবহার করবেন না
পাল

3

এজন্য std :: ভেক্টর ব্যবহার করুন। উদাহরণ স্বরূপ:

std::vector<int> values;
values.resize(n);

মেমরিটি গাদাতে বরাদ্দ করা হবে, তবে এটি কেবল একটি ছোট পারফরম্যান্সের অপূর্ণতা রাখে। তদ্ব্যতীত, স্ট্যাকের উপর বড় ডেটাব্লকগুলি বরাদ্দ না করাই বুদ্ধিমানের কারণ এটি আকারের চেয়ে সীমাবদ্ধ।


4
পরিবর্তনশীল দৈর্ঘ্যের অ্যারেগুলির জন্য একটি বড় অ্যাপ্লিকেশন হ'ল স্বেচ্ছাসেবী ডিগ্রি বহুবর্ষের মূল্যায়ন। সেক্ষেত্রে আপনার "ছোট পারফরম্যান্সের অপূর্ণতা" এর অর্থ "কোড সাধারণত কোডের ক্ষেত্রে পাঁচগুণ ধীর হয়।" এটি ছোট নয়।
এহেলপস

1
আপনি কেবল ব্যবহার করবেন না কেন std::vector<int> values(n);? resizeনির্মাণের পরে ব্যবহার করে আপনি নন-চলনযোগ্য প্রকারের নিষেধ করছেন।
LF

1

C99 VLA অনুমতি দেয়। এবং এটি কীভাবে ভিএলএ ঘোষণার বিষয়ে কিছু বাধা দেয়। বিশদ জন্য, স্ট্যান্ডার্ড 6.7.5.2 দেখুন। সি ++ ভিএলএ অনুমতি দেয় না। তবে জি ++ এটির অনুমতি দেয়।


আপনি যে স্ট্যান্ডার্ড অনুচ্ছেদে নির্দেশ করছেন তার লিঙ্কটি সরবরাহ করতে পারেন?
ভিনসেন্ট

0

এর মতো অ্যারেগুলি C99 এর অংশ, তবে মান সি ++ এর অংশ নয়। যেমনটি অন্যরা বলেছেন, একটি ভেক্টর সবসময়ই আরও ভাল সমাধান হয়, যার কারণেই সম্ভবত পরিবর্তনশীল মাপের অ্যারেগুলি সি ++ স্ট্যান্ডাটার্ডে (বা প্রস্তাবিত সি ++ 0 এক্স স্ট্যান্ডার্ডে) নয়।

বিটিডাব্লু, সি ++ স্ট্যান্ডার্ডটি কেন "কেন" সম্পর্কিত প্রশ্নের জন্য, মধ্যপন্থী ইউজনেট নিউজগ্রুপ কমপ্লেস্ট.স্টিডি। সি ++ এ যাওয়ার জায়গা।


6
-1 ভেক্টর সবসময় ভাল হয় না। প্রায়শই, হ্যাঁ সর্বদা, না। আপনার যদি কেবলমাত্র একটি ছোট অ্যারের প্রয়োজন হয়, এমন প্ল্যাটফর্মে আছেন যেখানে হিপ স্পেসটি ধীর হয় এবং আপনার গ্রন্থাগারের ভেক্টরের প্রয়োগটি হিপ স্পেস ব্যবহার করে, তবে এটি উপস্থিত থাকলে এই বৈশিষ্ট্যটি খুব ভাল হতে পারে।
প্যাট্রিক এম

-1

সংকলনের সময় মানটি যদি আপনি জানেন তবে আপনি নিম্নলিখিতটি করতে পারেন:

template <int X>
void foo(void)
{
   int values[X];

}

সম্পাদনা: আপনি একটি ভেক্টর তৈরি করতে পারেন যা স্ট্যাক বরাদ্দকারী (বরাদ্দ) ব্যবহার করে, যেহেতু বরাদ্দকারী একটি টেম্পলেট প্যারামিটার।


18
আপনি যদি সংকলনের সময় মানটি জানেন তবে আপনার কোনও টেম্পলেট লাগবে না। আপনার অ-টেম্পলেট ফাংশনে কেবল এক্স ব্যবহার করুন।
রব কেনেডি

3
কখনও কখনও কলার সংকলন সময়ে জানে এবং কলি তা করে না, এটি টেমপ্লেটগুলির জন্য ভাল। অবশ্যই, সাধারণ ক্ষেত্রে, রান-টাইম পর্যন্ত কেউ এক্সকে চেনে না।
কিওয়ারটি

আপনি কোনও এসটিএল বরাদ্দকারীতে বরাদ্দ ব্যবহার করতে পারবেন না - স্ট্যাক ফ্রেমটি নষ্ট হয়ে গেলে বরাদ্দ থেকে বরাদ্দ মেমরিটি মুক্তি দেওয়া হবে - সেই পদ্ধতিটি যখন মেমরির রিটার্ন বরাদ্দ করা উচিত when
অলিভার

-5

আমার কাছে একটি সমাধান রয়েছে যা আসলে আমার পক্ষে কাজ করেছিল। আমি একটি রুটিনে টুকরো টুকরো করার কারণে মেমরি বরাদ্দ করতে চাইনি যা অনেকবার চালানো দরকার। উত্তরটি অত্যন্ত বিপজ্জনক, সুতরাং এটি আপনার নিজের ঝুঁকিতে ব্যবহার করুন, তবে স্ট্যাকের স্থান সংরক্ষণ করতে এটি সমাবেশের সুবিধা নেয়। আমার নীচের উদাহরণটিতে একটি অক্ষর অ্যারে ব্যবহার করা হয়েছে (স্পষ্টতই অন্যান্য আকারের ভেরিয়েবলের আরও মেমরির প্রয়োজন হবে)।

void varTest(int iSz)
{
    char *varArray;
    __asm {
        sub esp, iSz       // Create space on the stack for the variable array here
        mov varArray, esp  // save the end of it to our pointer
    }

    // Use the array called varArray here...  

    __asm {
        add esp, iSz       // Variable array is no longer accessible after this point
    } 
}

বিপদগুলি এখানে অনেকগুলি তবে আমি কয়েকটি ব্যাখ্যা করব: 1. ভেরিয়েবলের আকারটি অর্ধেকের মাধ্যমে পরিবর্তন করা স্ট্যাকের অবস্থানটি মেরে ফেলবে the অ্যারে সীমানা ছাড়িয়ে যাওয়া অন্যান্য ভেরিয়েবল এবং সম্ভাব্য কোডটি নষ্ট করে দেবে 3.. এটি bit৪ বিটের মধ্যে কাজ করে না বিল্ড ... তার জন্য আলাদা সমাবেশ দরকার (তবে কোনও ম্যাক্রো সমস্যাটি সমাধান করতে পারে)। ৪. সংকলক নির্দিষ্ট (সংকলকগুলির মধ্যে চলতে সমস্যা হতে পারে)। আমি চেষ্টা করি নি তাই আমি জানি না।


... এবং আপনি যদি নিজেকে এটি রোল করতে চান তবে সম্ভবত কোনও আরআইআই ক্লাস ব্যবহার করবেন?
einpoklum

আপনি কেবল বুস্ট :: ধারক :: স্ট্যাটিক_ভেক্টর ব্যবহার করতে পারেন।
ভিক্টর সেহর 11:57

এমএসভিসির চেয়ে বেশি কাঁচা সমাবেশ রয়েছে এমন অন্যান্য সংকলকগুলির জন্য এটির সমতুল্য নেই। ভিসি সম্ভবত বুঝতে পেরেছেন যে এটি espপরিবর্তিত হয়েছে এবং এর অ্যাক্সেসগুলি স্ট্যাকের সাথে সামঞ্জস্য করবে, তবে উদাহরণস্বরূপ জিসিসি আপনি কেবল এটি সম্পূর্ণভাবে ভেঙে ফেলবেন - কমপক্ষে যদি আপনি অপ্টিমাইজেশান এবং -fomit-frame-pointerবিশেষত ব্যবহার করেন ।
রুসলান
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.