সি ++ এ বৃদ্ধি - কখন x ++ বা ++ এক্স ব্যবহার করবেন?


96

আমি বর্তমানে সি ++ শিখছি এবং কিছুক্ষণ আগে বর্ধিতকরণ সম্পর্কে শিখেছি। আমি জানি যে আপনি আগে ইনক্রিমেন্টেশন করতে "++ এক্স" এবং এর পরে "x ++" ব্যবহার করতে পারেন।

তবুও, আমি দু'জনের মধ্যে কখন ব্যবহার করতে পারি তা সত্যিই আমি জানি না ... আমি সত্যিই কখনও "++ x" ব্যবহার করি নি এবং জিনিসগুলি সর্বদা এতদূর ভাল কাজ করেছে - সুতরাং, আমি কখন এটি ব্যবহার করব?

উদাহরণ: একটি লুপের জন্য, কখন "++ x" ব্যবহার করা ভাল?

এছাড়াও, কেউ কীভাবে ব্যাখ্যা করতে পারে যে কীভাবে বিভিন্ন বর্ধিতকরণ (বা হ্রাস) কাজ করে? আমি সত্যিই কৃতজ্ঞ হবে।

উত্তর:


122

এটি পছন্দের প্রশ্ন নয়, কিন্তু যুক্তিযুক্ত।

x++বর্তমান বিবৃতিটি প্রক্রিয়া করার পরে ভেরিয়েবল এক্সের মান বৃদ্ধি করে ।

++xবর্তমান বিবৃতিটি প্রক্রিয়া করার আগে ভেরিয়েবল এক্সের মান বৃদ্ধি করে ।

সুতরাং আপনি যে যুক্তি লিখছেন তা ঠিক করুন decide

x += ++ii বৃদ্ধি করবে এবং i + 1 x এ যুক্ত করবে। x += i++আমি এক্স এ যুক্ত করব, তারপরে আমি ইনক্রিমেন্ট করব।


27
এবং দয়া করে নোট করুন যে লুপের জন্য, প্রাইমেটিভগুলিতে, একেবারেই কোনও পার্থক্য নেই। অনেকগুলি কোডিং শৈলী কখনই কোনও ইনক্রিমেন্ট অপারেটর ব্যবহার না করার পরামর্শ দেয় যেখানে এটি ভুল বোঝাবুঝি হতে পারে; অর্থাত্, x ++ বা ++ x কেবল তার নিজস্ব লাইনে থাকা উচিত, কখনও কখনও y = x ++ হিসাবে নয়। ব্যক্তিগতভাবে, আমি এটি পছন্দ করি না তবে এটি অস্বাভাবিক
মাইকেজ

4
এবং যদি তার নিজস্ব লাইনে ব্যবহার করা হয় তবে উত্পন্ন কোডটি প্রায় একই রকম হতে পারে তা নিশ্চিত।
নসরেডনা

14
এটি প্যাডেন্ট্রিগুলির মতো মনে হতে পারে (মূলত এটি কারণ :)) তবে সি ++ এ x++বর্ধনের xপূর্বে x++মান সহ একটি মূল্যবান, xএকটি ইনক্রিমেন্টের পরে মূল্য রয়েছে । যখন প্রকৃত বর্ধিত মান x এ ফিরে সংরক্ষণ করা হয় তখনই কোনও অভিব্যক্তি গ্যারান্টি দেয় না, কেবলমাত্র পরবর্তী গ্যারান্টি পয়েন্টের আগেই এটি ঘটে তা কেবল গ্যারান্টিযুক্ত। 'বর্তমান বিবৃতি প্রক্রিয়া করার পরে' কঠোরভাবে নির্ভুল নয় কারণ কিছু অভিব্যক্তির সিকোয়েন্স পয়েন্ট থাকে এবং কিছু বিবৃতি যৌগিক বিবৃতি হয়।
সিবি বেইলি

10
আসলে, উত্তরটি বিভ্রান্তিকর। পরিবর্তনশীল এক্স পরিবর্তিত সময়ে যে বিন্দু সম্ভবত অনুশীলনে পৃথক হয় না। পার্থক্যটি হ'ল x ++ x এর পূর্ববর্তী মানের একটি মূল্য ফেরত দিতে সংজ্ঞায়িত হয় যখন ++ x এখনও ভেরিয়েবল এক্সকে বোঝায়।
বিক্রয়বিটজে

4
@ বিউওলোফফ: উত্তরটি এমন অর্ডারকে বোঝায় যা বিদ্যমান নেই। যখন ইনক্রিমেন্টগুলি হয় তখন কিছু বলার মান নেই nothing সংকলকটি "x + = i ++" এরূপে প্রয়োগ করার অধিকারী: ইনট জে = আই; i = i + 1; x + = j; "(যেমন।" আমি "বর্তমানের বিবৃতি প্রক্রিয়াকরণের আগে" বর্ধিত করেছি) এই কারণেই "i = i ++" এর অপরিবর্তিত আচরণ রয়েছে এবং এর কারণেই আমি মনে করি যে উত্তরটির "টুইঙ্কিং" প্রয়োজন। "x এর বর্ণনা" + = ++ আমি "ঠিক আছে কারণ আদেশের কোনও পরামর্শ নেই:" আমি বৃদ্ধি করব এবং আমি এক্স + এ + 1 যুক্ত করব "
রিচার্ড কর্ডেন

53

স্কট মায়ার্স আপনাকে সেইসব অনুষ্ঠান ব্যতীত উপসর্গের অগ্রাধিকার পছন্দ করতে বলে যেখানে লজিক নির্দেশ দেয় যে পোস্টফিক্স উপযুক্ত।

"আরও কার্যকর সি ++" আইটেম # 6 - এটি আমার পক্ষে যথেষ্ট কর্তৃত্ব।

যারা বইটির মালিক নয় তাদের জন্য এখানে প্রাসঙ্গিক উক্তি রয়েছে। পৃষ্ঠা 32 থেকে:

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

এবং 34 পৃষ্ঠায়:

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


4
সংকলক যদি বুঝতে না পারে যে ইনক্রিমেন্টের আগে মানটি অযৌক্তিক, তবে এটি পোস্টফিক্স বর্ধিতকরণটি বেশ কয়েকটি নির্দেশে প্রয়োগ করতে পারে - পুরাতন মানটি অনুলিপি করুন, এবং তারপরে ইনক্রিমেন্ট। উপসর্গ বর্ধন সবসময় কেবল একটি নির্দেশ থাকা উচিত।
gnud

8
গতকাল আমি এটি জিসিসির সাথে পরীক্ষা করে দেখেছি: একটি লুপের জন্য যেখানে নির্বাহের পরে মানটি ফেলে দেওয়া হয় i++বা ++i, উত্পন্ন কোডটি একই।
জর্জিও

এটি লুপের বাইরে চেষ্টা করুন। একটি অ্যাসাইনমেন্টের আচরণ অবশ্যই আলাদা হতে হবে।
duffymo

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

4
আপনি স্কটি মায়ার্সকে আপনারা যা চান তা বিশ্বাস করতে পারেন তবে আপনার কোডটি যদি পারফরম্যান্স নির্ভর হয় তবে যে কোনও পারফরম্যান্সের মধ্যে পার্থক্য রয়েছে ++xএবং x++আসলে তা গুরুত্বপূর্ণ, আপনি অনেক বেশি গুরুত্বপূর্ণ যে আপনি আসলে এমন একটি সংকলক ব্যবহার করুন যা কোনও সংস্করণকেই পুরোপুরি এবং যথাযথভাবে অনুকূল করে তুলতে পারে যাই হোক না কেন প্রসঙ্গ "যেহেতু আমি এই কৃপণ পুরাতন হাতুড়িটি ব্যবহার করছি, আমি কেবল 43.3 ডিগ্রি কোণে নখ চালাতে পারি" কেবল 43.7 ডিগ্রি পেরেক চালিয়ে বাড়ি তৈরির পক্ষে একটি দুর্বল যুক্তি। একটি ভাল সরঞ্জাম ব্যবহার করুন।
অ্যান্ড্রু হেনেল

28

পুনরাবৃত্তি বাড়ানোর সময় সিপ্রেফারেন্স থেকে :

আপনি যদি পুরানো মান ব্যবহার না করে থাকেন তবে পোস্ট-ইনক্রিমেন্ট অপারেটরের (+++) প্রি-ইনক্রিমেন্ট অপারেটরকে (++ ইটার) পছন্দ করা উচিত। পোস্ট-ইনক্রিমেন্ট সাধারণত নিম্নলিখিত হিসাবে প্রয়োগ করা হয়:

   Iter operator++(int)   {
     Iter tmp(*this); // store the old value in a temporary object
     ++*this;         // call pre-increment
     return tmp;      // return the old value   }

স্পষ্টতই, এটি প্রাক-বর্ধনের চেয়ে কম দক্ষ।

প্রাক-বর্ধন অস্থায়ী বস্তু উত্পন্ন করে না। আপনার অবজেক্ট তৈরি করা ব্যয়বহুল হলে এটি একটি উল্লেখযোগ্য পার্থক্য আনতে পারে।


8

আমি কেবল খেয়াল করতে চাই যে জেনেটেড কোডটি একই রকম রয়েছে যদি আপনি প্রাক / পোস্টের বর্ধিতকরণ ব্যবহার করেন যেখানে সিমেন্টিক (প্রাক / পোস্টের) কোনও ব্যাপার না।

উদাহরণ:

pre.cpp:

#include <iostream>

int main()
{
  int i = 13;
  i++;
  for (; i < 42; i++)
    {
      std::cout << i << std::endl;
    }
}

post.cpp:

#include <iostream>

int main()
{

  int i = 13;
  ++i;
  for (; i < 42; ++i)
    {
      std::cout << i << std::endl;
    }
}

_

$> g++ -S pre.cpp
$> g++ -S post.cpp
$> diff pre.s post.s   
1c1
<   .file   "pre.cpp"
---
>   .file   "post.cpp"

4
কোনও পূর্ণসংখ্যার মতো আদিম ধরণের জন্য, হ্যাঁ। আপনি কি পরীক্ষা করে দেখেছেন যে কোনওটির মতো পার্থক্যটি কী হতে পারে std::map::iterator? অবশ্যই সেখানে দুটি অপারেটর পৃথক, তবে আমি যদি জানতে আগ্রহী যে কম্পাইলার ফলাফলটি ব্যবহার না করা হয় তবে পোস্টফিক্সটিকে উপসর্গের জন্য উপসর্গটিতে অনুকূলিত করবে কিনা তা নিয়ে আমি আগ্রহী। পোস্টফিক্স সংস্করণে পার্শ্ব প্রতিক্রিয়া থাকতে পারে - এই বলে মনে করি না it's
সেহ

এছাড়াও, ' সংকলক সম্ভবত বুঝতে পারে যে আপনার পার্শ্ব প্রতিক্রিয়া দরকার নেই এবং এটি অপ্টিমাইজ করা উচিত নয়' opালু কোড লেখার কোনও অজুহাত হওয়া উচিত নয় যে কোনও কারণ ছাড়াই আরও জটিল পোস্টফিক্স অপারেটরদের ব্যবহার করে, সম্ভবত এতদূর সত্য যে এই বিষয়টি বাদ দিয়ে অনুমিত শিক্ষাদানের উপকরণগুলি আপাত কারণে পোস্টফিক্স ব্যবহার করে এবং পাইকারের জন্য হোলসেল জুড়ে অনুলিপি করে।
আন্ডারস্কোর_

6

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

আরেকটি বিষয় উল্লেখযোগ্য, তবে এটি হ'ল বেশিরভাগ সংকলকগণ যখন সম্ভব হবে তখন এ জাতীয় অপ্রয়োজনীয় জিনিসগুলি অপ্টিমাইজ করতে সক্ষম হবেন, উদাহরণস্বরূপ উভয় বিকল্প এখানে একই কোডের দিকে নিয়ে যাবে:

for (int i(0);i<10;++i)
for (int i(0);i<10;i++)

5

আমি @ বিউওউফএফএফের সাথে একমত, যদিও স্পষ্টতার জন্য আমি সর্বদা বিবৃতিগুলিকে বিভক্ত করার পক্ষে পরামর্শ দেব যাতে যুক্তিটি একেবারে পরিষ্কার হয়, যেমন:

i++;
x += i;

বা

x += i;
i++;

সুতরাং আমার উত্তরটি হল আপনি যদি স্পষ্ট কোড লিখেন তবে এটি খুব কমই গুরুত্বপূর্ণ হওয়া উচিত (এবং যদি এটি গুরুত্বপূর্ণ হয় তবে আপনার কোড সম্ভবত যথেষ্ট পরিষ্কার নয়)।


2

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


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

1

আপনি পার্থক্যটি সঠিকভাবে ব্যাখ্যা করেছেন। এটি কেবলমাত্র লুপের মাধ্যমে প্রতি রান করার আগে বা তার পরে এক্স বাড়ানোতে চাইছে তার উপর নির্ভর করে। এটি আপনার প্রোগ্রামের যুক্তির উপর নির্ভর করে, উপযুক্ত কি।

এসটিএল-আইট্রেটরের সাথে কাজ করার ক্ষেত্রে একটি গুরুত্বপূর্ণ পার্থক্য (যা এই অপারেটরগুলি প্রয়োগ করে) এটি হ'ল এটি ++ পুনরুক্তি দ্বারা চিহ্নিত বস্তুর একটি অনুলিপি তৈরি করে, তারপরে ইনক্রিমেন্ট এবং তারপরে অনুলিপিটি প্রদান করে। ++ অন্যদিকে এটি প্রথমে ইনক্রিমেন্টটি করে এবং তারপরে পুনরাবৃত্তিকারী এখন যে পয়েন্টটি দেখায় তার একটি রেফারেন্স দেয় returns এটি বেশিরভাগ ক্ষেত্রে প্রাসঙ্গিক হয় যখন প্রতিটি বিট পারফরম্যান্স গণনা করা হয় বা আপনি যখন নিজের নিজস্ব এসটিএল-পুনরুক্তি প্রয়োগ করেন।

সম্পাদনা: উপসর্গ এবং প্রত্যয় চিহ্নের মিশ্রণ স্থির করে


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

1

++, এর postfix ফর্ম, - অপারেটর নিয়ম অনুসরণ করে ব্যবহার-তারপর-পরিবর্তন ,

উপসর্গ ফর্ম (++ x, - x) -র পরে-ব্যবহারের নিয়মটি অনুসরণ করে ।

উদাহরণ 1:

একাধিক মান << ব্যবহার করে cascaded করা হলে cout তারপর গণনার (যদি থাকে) থেকে সঞ্চালিত ডান-থেকে-বাম (যদি কেবল মুদ্রণ, বাম-থেকে-ডান উদাঃ থেকে সঞ্চালিত Val , তাহলে শুরুতে 10)

 cout<< ++val<<" "<< val++<<" "<< val;

মধ্যে ফলাফল হবে

12    10    10 

উদাহরণ 2:

টার্বো সি ++ তে, যদি ++ বা (যে কোনও রূপে) একাধিক উপস্থিতি একটি অভিব্যক্তিতে পাওয়া যায়, তবে প্রথমে সমস্ত উপসর্গ ফর্মগুলি গণনা করা হয় তবে অভিব্যক্তিটি মূল্যায়ন করা হয় এবং শেষ পর্যন্ত পোস্টফিক্স ফর্মগুলি গণনা করা হয় যেমন,

int a=10,b;
b=a++ + ++a + ++a + a;
cout<<b<<a<<endl;

এটি টার্বো সি ++ এ আউটপুট হবে

48 13

যদিও এটি আধুনিক সময়ের সংকলকটিতে আউটপুট হবে (কারণ তারা নিয়মগুলি কঠোরভাবে অনুসরণ করে)

45 13
  • দ্রষ্টব্য: এক বহিঃপ্রকাশে একই ভেরিয়েবলের উপর বৃদ্ধি / হ্রাস অপারেটরগুলির একাধিক ব্যবহারের প্রস্তাব দেওয়া হয় না। এই জাতীয়
    এক্সপ্রেশনগুলির পরিচালনা / ফলাফলগুলি সংকলক থেকে সংকলক পর্যন্ত পৃথক হয়।

এটি এমন নয় যে একাধিক ইনক / হ্রাস ক্রিয়াকলাপগুলি "সংকলক থেকে সংকলক পর্যন্ত পরিবর্তিত হয়", বরং আরও খারাপ: সিকোয়েন্স পয়েন্টগুলির মধ্যে এই জাতীয় একাধিক সংশোধন করার ফলে প্রোগ্রামটি অনির্ধারিত poison
আন্ডারস্কোর_

0

কোডের স্পষ্টতা বিবেচনা করার সময় ভাষার বাক্য গঠনটি বোঝা গুরুত্বপূর্ণ। একটি চরিত্রের স্ট্রিং অনুলিপি বিবেচনা করুন, উদাহরণস্বরূপ পোস্ট-ইনক্রিমেন্ট সহ:

char a[256] = "Hello world!";
char b[256];
int i = 0;
do {
  b[i] = a[i];
} while (a[i++]);

আমরা চাই যে স্ট্রিংয়ের শেষে শূন্য চরিত্রের (যা মিথ্যা পরীক্ষা করে) মুখোমুখি হয়ে লুপটি কার্যকর করা হোক। এর জন্য প্রাক-বর্ধিত মান পরীক্ষা করা এবং সূচককে বাড়ানো প্রয়োজন। তবে এই ক্রমে অগত্যা নয় - প্রাক-বর্ধনের সাথে এটি কোড করার একটি উপায় হ'ল:

int i = -1;
do {
  ++i;
  b[i] = a[i];
} while (a[i]);

এটি স্বাদের বিষয় যা পরিষ্কার and এবং যদি মেশিনটিতে রেজিস্ট্রারগুলির হাতছানি থাকে তবে উভয়ের ক্ষেত্রে একই রকম কার্যকর মৃত্যুর সময় থাকা উচিত, এমনকি যদি [i] কোনও ব্যয়বহুল বা পার্শ্ব প্রতিক্রিয়াযুক্ত কোনও ফাংশন থাকে। একটি উল্লেখযোগ্য পার্থক্য সূচকের প্রস্থান মূল্য হতে পারে।

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