C++0x چهار ویژگی جدید و مفید
-
p{direction:rtl;text-align:right}. برای کامپایل کدهای C++0x از آپشنِ –std=c++0x یا –std=gnu++0x استفاده میکنیم.(مثال: g++ Using_tht_char16_t.cpp --std=c++0x)
p{direction:rtl;text-align:right}. ۱ـ ویژگی Type inference
p{direction:rtl;text-align:right}. با استفاده از ویژگی Type inference تعیین نوع متغییر را به کامپایلر واگذار میکنیم. در گذشته در زبانهای مثل C و C++ ما بایستی نوع متغییر را برای کامپایلر مشخص میکردیم. مثال:
@int answer = 42; // answer is an int@
p{direction:rtl;text-align:right}. درحالیکه در زبانهای همچون Python متغییر بر حسب "آخرین" مقداری که میگیرد نوع آن مشخص میشود.مثال:
@answer = 42 // answer is now an int
answer = 42.1 // answer is now a float@p{direction:rtl;text-align:right}. در دهه اخیر یک روش سومی مورد توجه قرار گرفته است. و آن تشخیص نوع در هنگام کامپایل است به جای تشخیص نوع در هنگام اجرا.در نتیجه در این روش هیچگونه تغییر نوعی در هنگام اجرای برنامه رخ نمیدهد و بنابراین کامپایلر (بعد از تشخیص نوع متغییر) هنوز میتونه کد ماشین کارایی را مثل روش اول تولید کند.برای استفاده از این روش کلمه کلیدی auto را قبل از نام متغییر در هنگام تعریف متغییر به کار میبریم .مثال:
@auto x=7; // x is an int
x=4.3; // x is an int, so 4.3 is converted to 4
auto x=4.3 // ERROR: conflicting declaration@p{direction:rtl;text-align:right}. استفاده از auto میتونه خیلی مفید باشه به خصوص در مواردی که تشخیص نوع برای برنامه نویس سخت است استفاده ار آن بسیار لذت بخش خواهد بود.مثال:
@#include <iostream>
#include <map>
using namespace std;int main()
{
map<int, string> map1;
map1.insert(make_pair<int, string> (7, "8"));
auto mapit1 = map1.find(7); // type for mapit1 is std::map::iterator
cout << mapit1->second << endl;
}
@p{direction:rtl;text-align:right}. ۲-Initializer lists
p{direction:rtl;text-align:right}. در c++03 خاصیت initializer-list یا مقدار دهی اولیه از زبان C به ارث برده شده بود به این صورت که یک array یا یک struct میتوانست یک لیست از مقادیر را که داخل براکت محصور بودنند را بپذیرد و بدین ترتیب مقدار دهی میشدند.مثال:
@struct Object
{
float first;
int second;
};
= {8, 99, 2.3, 4.0, 5};
Object scalar = {0.43f, 10}; //One Object, with first=0.43f and second=10
Object anArray[] = {{13.4f, 3}, {43.28f, 29}, {5.934f, 17}}; //An array of three Objects
@ -
p{direction:rtl;text-align:right}. ادامه
p{direction:rtl;text-align:right}. حالا در c++0x ما میتوانیم این مفهوم را در مورد متغییر ها هم در نظر بگیریم. به مثال زیر توجه کنید.
@#include<iostream>
int main(){
int i{}; // or int i2={};
char* p{}; //NULL pointer
char c = {'A'};std::cout <<i<<std::endl;
std::cout <<c<<std::endl;
if(p==NULL){
std::cout << "p is NULL"<<std::endl;
}
return 0;
}@p{direction:rtl;text-align:right}. خروجی:
@
0
A
p is NULL@p{direction:rtl;text-align:right}. نکته: در c++0x هنگام مقدار دهی اولیه به وسیله {} دیگه type narrowing انجام نمیشه و int y{2.3} قابل قبول نیست و خطا میدهد.
p{direction:rtl;text-align:right}. جالب اینکه در c++0x این مفهوم به همه container های استاندار نیز گسترش یافته است . و میتوانیم آنها را در همان هنگام تعریف بصورت زیر مقدار دهی کنیم.
@std::vectorstd::string v = { "xyzzy", "plugh", "abracadabra" };
p{direction:rtl;text-align:right}. یا به روش زیر(فرقی نمیکند)
std::vectorstd::string v{ "xyzzy", "plugh", "abracadabra" };@p{direction:rtl;text-align:right}. این خصوصیت از template جدیدی به نام std::initializer_list<> که در استاندار جدید c++0x در نظر گرفته شده است نشأت میگیرد.
p{direction:rtl;text-align:right}. آبجکت سازی از initializer_list در c++0x تنها به یک طریق محدو شده است و آن هم استفاده از {} .با لیستی که داخل {} قرار میدهیم initializer_list ساخته میشود و این لیست به صورت copy-by-reference به initializer_list داده میشود و تغییر مقدار عناصر بعد از ساخته شدن آبجکت غیر ممکن است. به مثال زیر توجه کنید.
@#include<initializer_list>
#include<iostream>
int main(){std::initializer_list<int> list1 = {1,2,3,4,5};
auto f = list1.begin(); //first element
auto e = list1.end(); //one after last element
std::cout << *f ;//print 1
--e;
std::cout << *e;//print 5
return 0;
}@p{direction:rtl;text-align:right}. تابع begin() اشاره گری که به عنصر اول initializer_list اشاره میکند را برمیگرداند.
تابع end() به یکی بعد از عنصر آخر اشاره میکند.p{direction:rtl;text-align:right}. حال از آنجاییکه initializer_list یک نوع (type) است پس میتوان آنرا به عنوان یک پارامتر به توابع یا سازنده (constructor) کلاسها پاس داد. کاری که در container های استاندار c++0x انجام دادن اینه که اُومدن ویک سازنده دیگه بهشون اضافه کردن که std::initializer_list<> list رو به عنوان پارامتر ورودی میگیره . از این طریق قابلیت مقدار دهی اولیه را به آنها اضافه کردن.
p{direction:rtl;text-align:right}. ما هم میتونیم به هر کلاس یا template ای که مد نظر مون هست این قابلیت رو اضافه کنیم . فقط توجه کنید initializer_list را باید پیوست (include) کنیم.مثال:
@#include <initializer_list>
class SequenceClass {
public:
//constructor
SequenceClass(std::initializer_list<int> list){
//some of code
}
};
int main(){SequenceClass s = {1,2,3};
} @ -
p{direction:rtl;text-align:right}. ادامه
p{direction:rtl;text-align:right}. خوب حالا با ترکیب کردن دو مفهوم جدید auto و initializer_list کد زیر را در نظر میگیریم.
@#include <initializer_list>
using namespace std;
void display (initializer_list<int> arguments) {
for (auto p= arguments.begin(); p!= arguments.end(); ++p) {
// *p = *p * 2; → Not allowed to modify data
cout << *p << "\n";
}
}int main( )
{
display( {3, 77, 8, 1, 9} );
return 0;
}@p{direction:rtl;text-align:right}. ۳ـrange-based for
p{direction:rtl;text-align:right}. در c++ کد پیمایش یک لیست یا یک آرایه با استفاده از for طولانی است در حالیکه در زبانهای مثل جاوا و c# یک روش کوتا برای انجام این کار با استفاده از foreach وجود دارد.حالا c++0x ویژگی مشابه رو به for اضافه کرده که range-based for خوانده میشود و برای آرایه ها و initializer lists ها و تمامی container های استاندار کار میکنه.مثال زیر با استفاده از range-based for for مقدار تمامی عناصر my_array را دو برابر میکند.
@int my_array[5] = {1, 2, 3, 4, 5};
for (int &x : my_array) {
x *= 2;
}@p{direction:rtl;text-align:right}. یا مثال زیر که تمامی اعضای array را چاپ میکند.
@
#include<iostream>
int main(){
int array[]={1,3,5,7,11};for(int t : array)
std::cout<<t<<std::endl;return 0;
}@p{direction:rtl;text-align:right}. ۴- decltype
p{direction:rtl;text-align:right}. با استفاده از عملگر decltype در c++0x میتوانیم نوع یک متغییر یا عبارت را متوجه شویم.همچنین میتوانیم از آن برای تعیین نوع یک عبارت نیز استفاده کنیم.در مثال زیر تعیین نوع متغییر other_integer به استفاده از decltype(some_int) مشخص میشود.
@int some_int;
decltype(some_int) other_integer= 5;@p{direction:rtl;text-align:right}. استفاده از عملگر decltype در کنار استفاده از auto میتونه بسیار مفید واقع بشه از آنجاییکه نوع یک متغییر auto تنها بر کامپایلر معلوم است و نوعی که توسط عمگلر decltype مشخص خواهد شد بر حسب نوعی است متغییر auto در هنگام کامپایل به خود میگیرد.مثال:
@auto c = 0; // c has type int
auto d = c; // d has type int
decltype(c) e; // e has type int, the type of the entity named by c@p{direction:rtl;text-align:right}. همچنین decltype برای کسانی که از generic programming استفاده میکنند بسیار مفید است.
p{direction:rtl;text-align:right}. منابع:
http://drdobbs.com/cpp/231002092?pgno=2
http://en.wikipedia.org/wiki/C++11
http://www.ibm.com/developerworks/aix/library/au-gcc/index.html
http://cnevis.com/?p=213