আমাদের মধ্যে প্রশ্ন রয়েছে i++
এবং এর মধ্যে পারফরম্যান্সের পার্থক্য রয়েছে++i
সি এর ?
সি ++ এর উত্তর কী?
আমাদের মধ্যে প্রশ্ন রয়েছে i++
এবং এর মধ্যে পারফরম্যান্সের পার্থক্য রয়েছে++i
সি এর ?
সি ++ এর উত্তর কী?
উত্তর:
[নির্বাহী সংক্ষিপ্তসার: আপনার ব্যবহারের ++i
নির্দিষ্ট কারণ না থাকলে ব্যবহার করুন i++
]]
সি ++ এর জন্য উত্তরটি কিছুটা জটিল।
যদি i
একটি সাধারণ প্রকার হয় (কোনও সি ++ শ্রেণির উদাহরণ নয়), তবে সি এর জন্য দেওয়া উত্তর ("না কোনও পারফরম্যান্সের পার্থক্য নেই") ধারণ করে, যেহেতু সংকলক কোডটি তৈরি করছে।
যাইহোক, যদি i
কোনও সি ++ শ্রেণির উদাহরণ হয়, i++
এবং তখন ++i
কোনও একটি operator++
ফাংশনে কল করছে । এই ফাংশনগুলির জন্য এখানে একটি স্ট্যান্ডার্ড জোড় রয়েছে:
Foo& Foo::operator++() // called for ++i
{
this->data += 1;
return *this;
}
Foo Foo::operator++(int ignored_dummy_value) // called for i++
{
Foo tmp(*this); // variable "tmp" cannot be optimized away by the compiler
++(*this);
return tmp;
}
যেহেতু সংকলক কোডটি জেনারেট করে না, তবে কেবল একটি operator++
ফাংশনকে কল করছে, tmp
ভেরিয়েবল এবং এর সাথে সম্পর্কিত অনুলিপি নির্মাণকারীকে অপ্টিমাইজ করার কোনও উপায় নেই । যদি অনুলিপি নির্মাণকারী ব্যয়বহুল হয়, তবে এটির একটি উল্লেখযোগ্য পারফরম্যান্স প্রভাব থাকতে পারে।
হ্যাঁ. এখানে.
++ অপারেটর একটি ফাংশন হিসাবে সংজ্ঞায়িত বা নাও হতে পারে। আদিম ধরণের জন্য (int, ডাবল, ...) অপারেটরগুলি অন্তর্নির্মিত, তাই সংকলক সম্ভবত আপনার কোডটি অনুকূলিত করতে সক্ষম হবেন। তবে এমন কোনও অবজেক্টের ক্ষেত্রে যেটি ++ অপারেটরকে সংজ্ঞায়িত করে তা আলাদা।
অপারেটর ++ (int) ফাংশন অবশ্যই একটি অনুলিপি তৈরি করতে হবে। এটি কারণ পোস্টফিক্স ++ এটি ধারণ করে তার চেয়ে আলাদা মান ফেরত প্রত্যাশিত: এটি অবশ্যই তার মানটি একটি অস্থায়ী ভেরিয়েবলের মধ্যে ধারণ করে, এর মান বাড়িয়ে দেয় এবং টেম্পটি ফিরিয়ে দেয়। অপারেটর ++ (), উপসর্গ ++ এর ক্ষেত্রে কোনও অনুলিপি তৈরি করার দরকার নেই: অবজেক্টটি নিজে বৃদ্ধি করতে পারে এবং তারপরে কেবল নিজেই ফিরে আসতে পারে।
এখানে পয়েন্টটির একটি উদাহরণ দেওয়া হল:
struct C
{
C& operator++(); // prefix
C operator++(int); // postfix
private:
int i_;
};
C& C::operator++()
{
++i_;
return *this; // self, no copy created
}
C C::operator++(int ignored_dummy_value)
{
C t(*this);
++(*this);
return t; // return a copy
}
প্রতিবার যখন আপনি অপারেটরকে ++ (int) কল করবেন তখন আপনাকে অবশ্যই একটি অনুলিপি তৈরি করতে হবে এবং সংকলক এটি সম্পর্কে কিছুই করতে পারে না। পছন্দটি দেওয়া হলে, অপারেটর ++ () ব্যবহার করুন; এইভাবে আপনি একটি অনুলিপি সংরক্ষণ করবেন না। এটি অনেকগুলি ইনক্রিমেন্টের (বৃহত লুপ?) এবং / বা বড় অবজেক্টের ক্ষেত্রে তাৎপর্যপূর্ণ হতে পারে।
C t(*this); ++(*this); return t;
করবে দ্বিতীয় লাইনে আপনি এই পয়েন্টারটি ডান বাড়িয়ে দিচ্ছেন, তাই আপনি কীভাবে t
এটি বাড়িয়ে দিচ্ছেন তা কীভাবে আপডেট হবে। এর মানগুলি কি ইতিমধ্যে অনুলিপি করা হয়নি t
?
The operator++(int) function must create a copy.
না এটা না. এর চেয়ে বেশি অনুলিপিগুলি নেইoperator++()
যখন ইনক্রিমেন্ট অপারেটরগুলি বিভিন্ন অনুবাদ ইউনিটে থাকে তখন মামলার একটি মানদণ্ড এখানে। জি ++ 4.5 সহ সংকলক।
আপাতত স্টাইলের বিষয়গুলি উপেক্ষা করুন
// a.cc
#include <ctime>
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
int main () {
Something s;
for (int i=0; i<1024*1024*30; ++i) ++s; // warm up
std::clock_t a = clock();
for (int i=0; i<1024*1024*30; ++i) ++s;
a = clock() - a;
for (int i=0; i<1024*1024*30; ++i) s++; // warm up
std::clock_t b = clock();
for (int i=0; i<1024*1024*30; ++i) s++;
b = clock() - b;
std::cout << "a=" << (a/double(CLOCKS_PER_SEC))
<< ", b=" << (b/double(CLOCKS_PER_SEC)) << '\n';
return 0;
}
// b.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
for (auto it=data.begin(), end=data.end(); it!=end; ++it)
++*it;
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
ভার্চুয়াল মেশিনে g ++ 4.5 সহ ফলাফল (সময় সেকেন্ডে হয়):
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 1.70 2.39
-DPACKET_SIZE=50 -O3 0.59 1.00
-DPACKET_SIZE=500 -O1 10.51 13.28
-DPACKET_SIZE=500 -O3 4.28 6.82
আসুন এখন নীচের ফাইলটি নিই:
// c.cc
#include <array>
class Something {
public:
Something& operator++();
Something operator++(int);
private:
std::array<int,PACKET_SIZE> data;
};
Something& Something::operator++()
{
return *this;
}
Something Something::operator++(int)
{
Something ret = *this;
++*this;
return ret;
}
এটি বর্ধিতকরণে কিছুই করে না। যখন বর্ধনের ধ্রুবক জটিলতা থাকে তখন এটি কেসটি অনুকরণ করে।
ফলাফলগুলি এখন অত্যন্ত পরিবর্তিত হয়:
Flags (--std=c++0x) ++i i++
-DPACKET_SIZE=50 -O1 0.05 0.74
-DPACKET_SIZE=50 -O3 0.08 0.97
-DPACKET_SIZE=500 -O1 0.05 2.79
-DPACKET_SIZE=500 -O3 0.08 2.18
-DPACKET_SIZE=5000 -O3 0.07 21.90
আপনার যদি আগের মানটির প্রয়োজন না হয় তবে প্রাক-বৃদ্ধি ব্যবহার করার অভ্যাস করুন। এমনকি বিল্টিন টাইপের সাথেও সামঞ্জস্য বজায় রাখুন, আপনি এটিতে অভ্যস্ত হয়ে পড়বেন এবং যদি আপনি কোনও বিল্টিন টাইপকে কোনও কাস্টম টাইপের সাথে প্রতিস্থাপন করেন তবে অপ্রত্যাশিত পারফরম্যান্স ক্ষতি হ্রাসের ঝুঁকিটি চালাবেন না।
i++
বলে increment i, I am interested in the previous value, though
।++i
বলে increment i, I am interested in the current value
বা increment i, no interest in the previous value
। আবার, আপনি এখনই না থাকলেও আপনি অভ্যস্ত হয়ে যাবেন।অকালীন অপটিমাইজেশন হ'ল সমস্ত অশুভের মূল। যেমন অকাল হতাশা।
for (it=nearest(ray.origin); it!=end(); ++it) { if (auto i = intersect(ray, *it)) return i; }
, প্রকৃত বৃক্ষ কাঠামোর (বিএসপি, কেডি, কোয়াডট্রি, অক্ট্রি গ্রিড ইত্যাদি) কখনও মনে করবেন না। এ ধরনের পুনরুক্তিকারীর কিছু রাষ্ট্র, যেমন বজায় রাখার জন্য প্রয়োজন হবে parent node
, child node
, index
এবং যে ভালো জিনিস। সব মিলিয়ে আমার অবস্থানটি, এমনকি যদি কয়েকটি মাত্র উদাহরণ উপস্থিত থাকে, ...
এটি বলা সম্পূর্ণভাবে সঠিক নয় যে সংকলক পোস্টফিক্স ক্ষেত্রে অস্থায়ী পরিবর্তনীয় অনুলিপিটিকে অপ্টিমাইজ করতে পারে না। ভিসির সাথে একটি দ্রুত পরীক্ষা দেখায় যে এটি কমপক্ষে কিছু ক্ষেত্রে এটি করতে পারে।
নিম্নলিখিত উদাহরণে, উত্পন্ন কোডটি উপসর্গ এবং পোস্টফিক্সের জন্য অভিন্ন, উদাহরণস্বরূপ:
#include <stdio.h>
class Foo
{
public:
Foo() { myData=0; }
Foo(const Foo &rhs) { myData=rhs.myData; }
const Foo& operator++()
{
this->myData++;
return *this;
}
const Foo operator++(int)
{
Foo tmp(*this);
this->myData++;
return tmp;
}
int GetData() { return myData; }
private:
int myData;
};
int main(int argc, char* argv[])
{
Foo testFoo;
int count;
printf("Enter loop count: ");
scanf("%d", &count);
for(int i=0; i<count; i++)
{
testFoo++;
}
printf("Value: %d\n", testFoo.GetData());
}
আপনি ++ টেস্টফু বা টেস্টফু ++ করেন না কেন আপনি এখনও একই ফলাফল কোড পাবেন। প্রকৃতপক্ষে, ব্যবহারকারীর কাছ থেকে গণনা না পড়ে, অপ্টিমাইজার পুরো জিনিসটিকে একটি ধ্রুবক পর্যন্ত নামিয়ে দেয়। আমার স্নাতকের:
for(int i=0; i<10; i++)
{
testFoo++;
}
printf("Value: %d\n", testFoo.GetData());
নিম্নলিখিত প্রতিক্রিয়া:
00401000 push 0Ah
00401002 push offset string "Value: %d\n" (402104h)
00401007 call dword ptr [__imp__printf (4020A0h)]
সুতরাং যদিও এটি অবশ্যই পোস্টফিক্স সংস্করণটি ধীরে ধীরে হতে পারে, তবে এটি ভাল হতে পারে যে আপনি যদি এটি ব্যবহার না করেন তবে অস্থায়ী অনুলিপি থেকে মুক্তি পাওয়ার জন্য অপটিমাইজার যথেষ্ট ভাল।
গুগল সি ++ স্টাইল গাইড বলেছেন:
প্রিঙ্ক্রেমেন্ট এবং প্রিডিক্রেমেন্ট
পুনরাবৃত্তকারী এবং অন্যান্য টেম্পলেট অবজেক্ট সহ বর্ধিতকরণ এবং হ্রাস অপারেটরগুলির উপসর্গ ফর্ম (++ i) ব্যবহার করুন।
সংজ্ঞা: যখন কোনও ভেরিয়েবল বর্ধিত হয় (++ i বা i ++) বা হ্রাস (- ii বা i--) এবং অভিব্যক্তির মান ব্যবহার করা হয় না, তখন অবশ্যই সিদ্ধান্ত নিতে হবে (প্রবণতা) বা উত্তর-সংযোগ (হ্রাস)।
পেশাদাররা: যখন রিটার্ন মানটিকে অগ্রাহ্য করা হয়, তখন "প্রাক" ফর্ম (++ i) কখনই "পোস্ট" ফর্ম (i ++) এর চেয়ে কম দক্ষ হয় না এবং প্রায়শই আরও দক্ষ হয়। এটি কারণ পোস্ট-ইনক্রিমেন্ট (বা হ্রাস) এর জন্য i এর একটি অনুলিপি প্রয়োজন যা অভিব্যক্তির মান। আমি যদি একজন পুনরুক্তিকারী বা অন্যান্য অ-স্কেলার প্রকার হয় তবে আমার অনুলিপি ব্যয়বহুল হতে পারে। যেহেতু মূল্য উপেক্ষা করা হয় যখন দুটি ধরণের ইনক্রিমেন্ট একই রকম আচরণ করে, তবে কেন সবসময় প্রাক-বৃদ্ধি বৃদ্ধি করা হয় না?
কনস: অভিব্যক্তির মানটি বিশেষত লুপের ক্ষেত্রে ব্যবহার না করা হলে পোস্ট-ইনক্রিমেন্ট ব্যবহারের Cতিহ্য সি তে উন্নত হয়েছিল। "সাবজেক্ট" (i) ইংরেজির মতো "ক্রিয়া" (++) এর আগে যেহেতু কেউ কেউ পোস্ট-ইনক্রিমেন্ট পড়া সহজ মনে করেন।
সিদ্ধান্ত: সাধারণ স্কেলারের (অ-অবজেক্ট) মানগুলির জন্য একটি ফর্মকে প্রাধান্য দেওয়ার কোনও কারণ নেই এবং আমরা উভয়কেই অনুমতি দিই। পুনরাবৃত্তকারী এবং অন্যান্য টেম্পলেট ধরণের জন্য, প্রাক-বর্ধন ব্যবহার করুন।
আমি খুব সম্প্রতি কোড টক-এ অ্যান্ড্রু কোইনিগের একটি দুর্দান্ত পোস্টটি উল্লেখ করতে চাই।
http://dobbscodetalk.com/index.php?option=com_myblog&show=Efficiency-versus-intent.html&Itemid=29
আমাদের সংস্থায় আমরা যেখানে + প্রযোজ্য ধারাবাহিকতা এবং পারফরম্যান্সের জন্য++ এর কনভেনশন ব্যবহার করি। তবে অ্যান্ড্রু অভিপ্রায় বনাম পারফরম্যান্সের বিষয়ে ওভার-স্ক্রোল ডিটেইল উত্থাপন করেছেন। এমন সময় আছে যখন আমরা ++ ইটারের পরিবর্তে ++ ব্যবহার করতে চাই।
সুতরাং, প্রথমে আপনার অভিপ্রায় স্থির করুন এবং প্রাক বা পোস্ট যদি গুরুত্বপূর্ণ না হয় তবে প্রাকের সাথে যান কারণ এতে অতিরিক্ত বস্তুর সৃষ্টি এড়ানো এবং নিক্ষেপ করে কিছুটা পারফরম্যান্স উপকার পাবেন।
@Ketan
... অভিপ্রায় বনাম পারফরম্যান্সের বিষয়ে ওভার-লুক করা বিশদ উত্থাপন করে। এমন সময় আছে যখন আমরা ++ ইটারের পরিবর্তে ++ ব্যবহার করতে চাই।
স্পষ্টতই পোস্ট এবং প্রাক-ইনক্রিমেন্টের বিভিন্ন শব্দার্থবিজ্ঞান রয়েছে এবং আমি নিশ্চিত যে সকলেই সম্মত হন যে ফলাফলটি ব্যবহার করার সময় আপনার উপযুক্ত অপারেটরটি ব্যবহার করা উচিত। আমি মনে করি ফলাফলটি বাতিল হয়ে গেলে ( for
লুপগুলিতে) একটি করা উচিত যা প্রশ্ন । উত্তর এই প্রশ্ন (এই প্রোগ্রামটিতে) যে, যেহেতু কর্মক্ষমতা বিবেচনার শ্রেষ্ঠ সময়ে তুচ্ছ হয়, আপনি কি আরো প্রাকৃতিক কি উচিত নয়। আমার ++i
পক্ষে আরও স্বাভাবিক তবে আমার অভিজ্ঞতা আমাকে বলে যে আমি সংখ্যালঘুতে আছি এবং ব্যবহার i++
করা বেশিরভাগের জন্য কম ধাতব ওভারহেডের কারণ হবে লোকেরা আপনার কোড পড়তে ।
সর্বোপরি যে কারণে ভাষাটি বলা হয় না "++C
" । [*]
[*] ++C
আরও যুক্তিযুক্ত নাম হওয়া সম্পর্কে বাধ্যতামূলক আলোচনা sertোকান ।
যখন ব্যবহার করছেন না ফেরত মান কম্পাইলার ক্ষেত্রে একটি অস্থায়ী ব্যবহার না করার নিশ্চিত করা হয় আমি ++, । দ্রুত হওয়ার গ্যারান্টি নেই তবে ধীর না হওয়ার গ্যারান্টি রয়েছে।
রিটার্ন মান ব্যবহার করার সময় i++ প্রসেসরটিকে বৃদ্ধি এবং বাম দিক উভয়কে পাইপলাইনে ঠেকাতে দেয় যেহেতু তারা একে অপরের উপর নির্ভর করে না। ++ আমি পাইপলাইনটি স্টল করতে পারি কারণ প্রসেসরটি বর্ধিত দিকটি শুরু করতে পারে না যতক্ষণ না প্রি-ইনক্রিমেন্ট অপারেশনটি পুরো পথটি সরিয়ে না দেওয়া হয়। আবার, একটি পাইপলাইন স্টল গ্যারান্টিযুক্ত নয়, যেহেতু প্রসেসরটি অন্যান্য দরকারী জিনিসগুলি ভিতরে থাকতে পারে।
চিহ্নিত করুন: কেবলমাত্র ইঙ্গিত করতে চেয়েছিলেন যে অপারেটরটি ++ এর ভাল প্রার্থীদের অন্তর্ভুক্ত করা উচিত, এবং যদি সংকলক এটি করতে নির্বাচন করে তবে বেশিরভাগ ক্ষেত্রে অপ্রয়োজনীয় অনুলিপি মুছে ফেলা হবে। (যেমন পিওডির ধরণগুলি, যা সাধারণত পুনরাবৃত্তকারী হয়))
এটি বলেছে, বেশিরভাগ ক্ষেত্রে ++ ইটার ব্যবহার করা আরও ভাল স্টাইল। :-)
মধ্যে কর্মক্ষমতা পার্থক্য ++i
এবং i++
যখন আপনি যেমন মূল্য ফেরার ফাংশন অপারেটরদের মনে করি এবং কিভাবে তারা প্রয়োগ করা হয় আরো আপাত হবে। এটিকে সহজভাবে বোঝার জন্য কি ঘটছে করতে, নিম্নলিখিত কোড উদাহরণ ব্যবহার করবে int
যেমন যদি এটি একটি ছিল struct
।
++i
পরিবর্তনশীল বৃদ্ধি করে, তারপরে ফলাফলটি দেয়। এটি যথাস্থানে এবং ন্যূনতম সিপিইউ সময় সহ করা যেতে পারে, অনেক ক্ষেত্রে কেবলমাত্র একটি লাইন কোডের প্রয়োজন:
int& int::operator++() {
return *this += 1;
}
তবে একই কথা বলা যায় না i++
।
পোস্ট-ইনক্রিমেন্টিং, i++
প্রায়শই বর্ধিত হওয়ার আগে আসল মান ফেরত দেখা যায় । যাইহোক, একটি ফাংশন শুধুমাত্র ফলে যখন এটি সমাপ্ত হয় আসতে পারেন । ফলস্বরূপ, আসল মান সম্বলিত ভেরিয়েবলের একটি অনুলিপি তৈরি করা, ভেরিয়েবলকে বৃদ্ধি করা, তারপরে মূল মানটি ধারণ করে অনুলিপিটি প্রদান করা প্রয়োজনীয় হয়ে পড়ে:
int int::operator++(int& _Val) {
int _Original = _Val;
_Val += 1;
return _Original;
}
প্রাক-বৃদ্ধি এবং উত্তর-বৃদ্ধির মধ্যে যখন কোনও কার্যকরী পার্থক্য না থাকে, তখন সংকলকটি অপ্টিমাইজেশন সম্পাদন করতে পারে যে উভয়ের মধ্যে কোনও পারফরম্যান্সের পার্থক্য নেই। তবে, যদি কোনও যৌগিক ডেটা টাইপ যেমন একটি struct
বা class
জড়িত থাকে তবে অনুলিপি পোস্ট-ইনক্রিমেন্টে অনুলিপি করা হবে এবং যদি একটি গভীর অনুলিপি প্রয়োজন হয় তবে এই অপ্টিমাইজেশন সম্পাদন করা সম্ভব হবে না। যেমন, প্রাক-বৃদ্ধি সাধারণত দ্রুত হয় এবং পোস্ট-ইনক্রিমেন্টের চেয়ে কম মেমরির প্রয়োজন হয়।
@ মার্ক: আমি আমার পূর্ববর্তী উত্তরটি মুছলাম কারণ এটি কিছুটা উল্টানো ছিল এবং কেবলমাত্র এটির জন্য একটি ডাউনটোটের যোগ্য ছিল। আমি আসলে এটি একটি ভাল প্রশ্ন এই অর্থে যে এটি জিজ্ঞাসা করে যে অনেক মানুষের মনে কি আছে।
সাধারণ উত্তরটি হ'ল ++ i আমি ++ এর চেয়ে দ্রুত এবং এটি সন্দেহ নেই তবে বড় প্রশ্নটি "আপনার কখন যত্ন করা উচিত?"
পুনরবৃদ্ধি পুনরুক্তিতে ব্যয় করা সিপিইউ সময়ের ভগ্নাংশ যদি 10% এর চেয়ে কম হয়, তবে আপনি হয়ত যত্ন করবেন না।
যদি বার্ষিকী পুনরবৃদ্ধি করতে ব্যয় করা সিপিইউ সময়ের ভগ্নাংশটি 10% এর চেয়ে বেশি হয়, আপনি কোন স্টেটমেন্টগুলি পুনরাবৃত্তি করছে তা আপনি দেখতে পারেন। আপনি পুনরাবৃত্তকারী ব্যবহার না করে কেবল পূর্ণসংখ্যার বৃদ্ধি করতে পারেন কিনা তা দেখুন। সম্ভাবনাগুলি আপনি যা করতে পেরেছিলেন এবং এটি কিছুটা বিবেচনায় কম কাঙ্ক্ষিত হলেও সম্ভাবনাগুলি বেশ ভাল আপনি সেই পুনরাবৃত্তকারীগুলিতে ব্যয় করা সমস্ত সময় সাশ্রয় করবেন।
আমি এমন একটি উদাহরণ দেখেছি যেখানে 90% সময়ের মধ্যে পুনরাবৃত্তির পরিমাণ বাড়ানো ছিল। সেক্ষেত্রে, পূর্ণসংখ্যার-বর্ধিতকরণে মূলত সেই পরিমাণ দ্বারা কার্যকরকরণের সময় হ্রাস। (যেমন 10x স্পিডআপের চেয়ে ভাল)
@wilhelmtell
সংকলক অস্থায়ীভাবে elide করতে পারেন। অন্য থ্রেড থেকে ভারব্যাটিম:
সি ++ সংকলকটিকে স্ট্যাক ভিত্তিক টেম্পোরারিগুলি মুছে ফেলার অনুমতি দেওয়া হয় এমনকি যদি এটি করে তবে এর আচরণগত আচরণ পরিবর্তন হয়। ভিসি 8 এর জন্য এমএসডিএন লিঙ্ক:
http://msdn.microsoft.com/en-us/library/ms364057(VS.80).aspx
আপনি যে বিল্ট-ইন প্রকারের যেখানে কোনও পারফরম্যান্স সুবিধা নেই সেখানে নিজের জন্য একটি ভাল অভ্যাস তৈরি করা কেন ++ i ব্যবহার করা উচিত তার কারণ।
উভয়ই তত দ্রুত;) আপনি যদি এটি চান যে এটি প্রসেসরের জন্য একই গণনা, এটি কেবল এটির ক্রম হিসাবে এটি করা হয় যা ভিন্ন।
উদাহরণস্বরূপ, নিম্নলিখিত কোড:
#include <stdio.h>
int main()
{
int a = 0;
a++;
int b = 0;
++b;
return 0;
}
নিম্নলিখিত সমাবেশ উত্পাদন:
0x0000000100000f24 <main+0>: push %rbp 0x0000000100000f25 <main+1>: mov %rsp,%rbp 0x0000000100000f28 <main+4>: movl $0x0,-0x4(%rbp) 0x0000000100000f2f <main+11>: incl -0x4(%rbp) 0x0000000100000f32 <main+14>: movl $0x0,-0x8(%rbp) 0x0000000100000f39 <main+21>: incl -0x8(%rbp) 0x0000000100000f3c <main+24>: mov $0x0,%eax 0x0000000100000f41 <main+29>: leaveq 0x0000000100000f42 <main+30>: retq
আপনি দেখতে পাচ্ছেন যে একটি ++ এবং বি ++ এর জন্য এটি একটি স্মৃতিসৌধিক, তাই এটি একই ক্রিয়াকলাপ;)
ফলাফলটি কখন অব্যবহৃত হবে তা উদ্দেশ্যযুক্ত প্রশ্ন ছিল (এটি সি এর প্রশ্ন থেকে পরিষ্কার)। প্রশ্নটি "সম্প্রদায় উইকি" হওয়ায় কেউ কি এটিকে সমাধান করতে পারবেন?
অকাল অপ্টিমাইজেশান সম্পর্কে, নথ প্রায়শই উদ্ধৃত হয়। সেটা ঠিক. তবে ডোনাল্ড নুথ কখনই সেই ভয়াবহ কোডটি ব্যবহার করতে পারবেন না যা আপনি এই দিনগুলিতে দেখতে পাচ্ছেন। জাভা ইন্টিজারগুলির মধ্যে কখনই a = b + c দেখেছেন? যার পরিমাণ 3 বক্সিং / আনবক্সিং রূপান্তর। এ জাতীয় জিনিস এড়ানো গুরুত্বপূর্ণ। এবং অকেজোভাবে ++ i এর পরিবর্তে i ++ লেখা একই ভুল। সম্পাদনা: ফ্রেসনেল এটিকে একটি মন্তব্যে খুব সুন্দর করে বলেছে, এটি "অকালীন নিরাশা যেমন অকাল অপটিমাইজেশনটি মন্দ," হিসাবে সংক্ষেপে বলা যেতে পারে।
এমনকি লোকেরা যে +++ এর বেশি ব্যবহার করে থাকে তা হ'ল দুর্ভাগ্যজনক সি উত্তরাধিকার, কে ওআরআর দ্বারা ধারণামূলক ভুলের কারণে ঘটে (যদি আপনি অভিপ্রায় যুক্তি অনুসরণ করেন তবে এটি একটি যৌক্তিক উপসংহার; এবং কেএন্ডআরকে রক্ষা করা কারণ তারা কে ও আর আর অর্থহীন নয়, তারা দুর্দান্ত, তবে তারা ভাষা ডিজাইনার হিসাবে দুর্দান্ত নয়; সি ডিজাইনে অসংখ্য ভুল রয়েছে, পেয়ে যায় () থেকে স্ট্রাইকপি () থেকে স্ট্রেনসিপি () এপিআই (প্রথম দিন পর্যন্ত এটি স্ট্রলসিপি () এপিআই থাকা উচিত) )।
বিটিডব্লিউ, আমি এমন একজন যারা আমি ++ পড়ার জন্য বিরক্তিকর সন্ধান করতে সি ++ তে যথেষ্ট ব্যবহার করি নি। তবুও, আমি যেহেতু আমি স্বীকার করি যে এটি সঠিক use
++i
চেয়ে বেশি বিরক্তিকর আমি আর পাই নাi++
(বাস্তবে আমি এটি আরও শীতল পেয়েছি), তবে আপনার পোস্টের বাকী অংশটি আমার সম্পূর্ণ স্বীকৃতি পেয়েছে। হতে পারে একটি বিন্দু যুক্ত করুন "অকাল অনুকূলতা যেমন খারাপ, তেমনি অকাল হতাশা"
strncpy
তারা সেই সময় যে ফাইল ফাইলগুলি ব্যবহার করত সেগুলিতে একটি উদ্দেশ্য সরবরাহ করেছিল; ফাইলের নামটি একটি 8-চরিত্রের বাফার এবং এটি নাল-টার্মিনেট করতে হবে না। ভাষার বিবর্তনের ভবিষ্যতে 40 বছর না দেখার জন্য আপনি তাদের দোষ দিতে পারবেন না।
strlcpy()
সত্যটি প্রমাণিত হয়েছিল যে এটি এখনও আবিষ্কার হয়নি।
লোকদেরকে জ্ঞানের রত্ন প্রদানের সময়;) - সি ++ পোস্টফিক্স ইনক্রিমেন্টটি উপসর্গের বর্ধনের মতোই একই রকম আচরণ করার সহজ কৌশল আছে (এটি আমার জন্য এটি উদ্ভাবিত হয়েছে, তবে এটি অন্য লোকের কোডেও দেখেছি, তাই আমি নই একা)।
মূলত, কৌশলটি হ'ল প্রত্যাবর্তনের পরে বর্ধিততা স্থগিত করার জন্য সহায়ক শ্রেণী ব্যবহার করা এবং আরএআইআই উদ্ধার করতে আসে
#include <iostream>
class Data {
private: class DataIncrementer {
private: Data& _dref;
public: DataIncrementer(Data& d) : _dref(d) {}
public: ~DataIncrementer() {
++_dref;
}
};
private: int _data;
public: Data() : _data{0} {}
public: Data(int d) : _data{d} {}
public: Data(const Data& d) : _data{ d._data } {}
public: Data& operator=(const Data& d) {
_data = d._data;
return *this;
}
public: ~Data() {}
public: Data& operator++() { // prefix
++_data;
return *this;
}
public: Data operator++(int) { // postfix
DataIncrementer t(*this);
return *this;
}
public: operator int() {
return _data;
}
};
int
main() {
Data d(1);
std::cout << d << '\n';
std::cout << ++d << '\n';
std::cout << d++ << '\n';
std::cout << d << '\n';
return 0;
}
কিছু ভারী কাস্টম পুনরাবৃত্তকারী কোডের জন্য উদ্ভাবিত এবং এটি রান-টাইমকে হ্রাস করে। উপসর্গ বনাম পোস্টফিক্সের দাম এখন একটি রেফারেন্স, এবং এটি যদি কাস্টম অপারেটর যদি ভারী ঘোরাঘুরি করে, উপসর্গ এবং পোস্টফিক্সটি আমার জন্য একই রান-টাইম অর্জন করেছিল।
++i
তুলনায় দ্রুত i++
এটির কারণ এটি মানটির একটি পুরানো অনুলিপি ফেরত দেয় না।
এটি আরও স্বজ্ঞাত:
x = i++; // x contains the old value of i
y = ++i; // y contains the new value of i
এই সি উদাহরণটি আপনি আশা করতে পারেন "12" এর পরিবর্তে "02" মুদ্রণ করে:
#include <stdio.h>
int main(){
int a = 0;
printf("%d", a++);
printf("%d", ++a);
return 0;
}
#include <iostream>
using namespace std;
int main(){
int a = 0;
cout << a++;
cout << ++a;
return 0;
}