rox_rook đang dùng IDE & compiler nào mà gặp lỗi kỳ cục này ?
Đây là 1 lỗi cực kì khó chịu mà theo mình nghĩ khi viết code chúng ta nên để ý đến vấn đề này, hôm nay ngòi viết mà debug gần 3 tiếng đồng hồ mới tìm ra hic hic. Nếu mọi người ai cũng biết thì bỏ qua cho mình nhé T_T. Vì thực sự mình thấy nó cũng quan trọng nên muốn ghi lại cho nhớ dai thêm 1 chút hì hì !
Trong class nó có 1 thằng gọi là bộ khởi tạo thành viên (member-initialization) và nó sẽ khác với khi chúng ta dùng phép gán khi khởi tạo cho dữ liệu. Xét ví dụ sau :
Cách khởi tạo cho đúng phải là ví dụ :PHP Code:class Person{
private:
int age;
string name;
public:
Person(int a, const string & n)
{
//chú ý chỗ này là phép gán chứ không phải khởi tạo.
age = a;
name = n;
}
};
Tuy nhiên ở ví dụ trên thì sự khác biệt sẽ chẳng ảnh hưởng lắm, nhưng nó sẽ khác khi ta bắt buộc phải dùng bộ khởi tạo khi làm việc với dữ liệu là const, reference và sub-objects.PHP Code:class Person
{
//..
public:
Person(int a, const string & n) : age (a), name (n)
{}
};
Ví dụ :
Đây là cách khởi tạo hoàn toàn hợp lệ, vì nó theo đúng thứ tự mà chúng ta khai báo các dữ liệu thành viên trong class Foo. Nhưng tiếp theo chúng ta sẽ xét ví dụ sau :PHP Code:class Foo
{
private:
int & r; // reference
const int MAX; // const
Person p; //object
public:
explicit Foo(int& n) : r(n), MAX(100), p (MAX,"John D."){}
};
Vì chúng ta đã khai báo làPHP Code:class BadFoo
{
private:
int & r;
Person p;
const int MAX;
public:
explicit BadFoo(int& n)//Nguy hiểm đang chờ đợi
: r(n), MAX(100), p (MAX,"John D.") {}
};
Nên bộ khởi tạo sẽ tự động kích hoạt theo thứ tự sau trong cái list mà chúng ta khai báo ở dưới cho constructor :PHP Code:1. int &r
2. Person p;
3. const int Max;
và thế là thằng MAX sẽ trở thành rac, mà debug mấy lỗi này thì đúng là điên cả người T_T.PHP Code:r(n), MAX(100), p (MAX,"John D.")
Trong khi thứ tự đúng phải là như sau :
PHP Code:explicit BadFoo(int& n)
: r(n), p (MAX,"John D."), MAX(100) {}
rox_rook đang dùng IDE & compiler nào mà gặp lỗi kỳ cục này ?
Dạ, em dùng thằng Devcpp thì ok, nhưng với thằng Visual 2008 thì nó lại bắt lỗi. Em cũng không rõ có phải vậy không ? Nhưng em search trên google thì đọc được quả thật có lỗi này, thế là em sữa lại thì ok. Em cũng không biết có chắc không nữa ?
Anh test với VC++2008 Express, với thứ tự khai báo:
Thì dù có đổi thứ tự initialize list theo sau constructor như thế nào đi nữa thì vẫn bị bug, p.age = rác (0xCCCCCCCC).Code:int &r; // reference Person p; //object const int MAX; // const
rox_rook đoán thử tại sao !
Hì hì, em hiểu ý anh rùi T_T. Do thứ tự này có vấn đề :
Thằng MAX chưa được khởi tạo nên dù có thế nào đi chăng nữa thì age phải là garbage .T_T ! Đưa ví dụ cũng ẩu ~~! Thanks anh đã nhắc nhở T_TPHP Code:1. int &r
2. Person p;
3. const int Max;
Còn cái lỗi thứ tự này em nghĩ nó đúng đấy anh à, vì em cũng đọc thêm 1 cuốn sách C++ in action, và nó cũng đề cập đến vấn đề này.
Tui nghĩ như vầy:
1) Đây là lỗi của người lập trình, chớ không phải lỗi của trình biên dịch
Theo như: http://www.devx.com/getHelpOn/10Minu...ion/17298/1954 thì
(bạn rox_rook có nói là ok với Devcpp, nhưng bị lỗi với Visual 2008C++ ensures that members are initialized in the order of their declaration in the class
(C++: các thuộc tính được khởi tạo theo thứ tự đã khai báo trong class)
class Thing
{
private:
int & ref; // reference member
const int MAX; // const member
vector arr;
public:
Thing(int& r) : ref(r), MAX(100), arr (MAX) {}
};
Notice that the member MAX serves as arr's initializer. This is perfectly legal. C++ ensures that members are initialized in the order of their declaration in the class. If you change the member initialization list to:
Thing(int& r) : arr(MAX), MAX(100), ref(r) {}
The members will still be initialized in the following order: ref, MAX, and arr. However, pay attention to the members' order inside the class. Doing something like this causes unpredictable results at runtime:
class BadThing
{
private:
int & ref;
Array arr; //wrong, should appear after MAX
const int MAX;
};
The problem is that MAX hasn't been initialized when its value is passed to arr's constructor.
Nhưng nếu đặc tả của C++ là "ensures that members are initialized in the order of their declaration in the class" thì VC++2008 không có lỗi ở chỗ này)
2) dấy phẩy (comma, ',') có 2 vài trò: toán tử (operator) và dấu phân cách (separator)
Theo như http://msdn2.microsoft.com/en-us/library/zs06xbxh.aspx thì
Như vậy dấu phẩy trong danh sách khởi tạo "Thing(int& r) : ref(r), MAX(100), arr (MAX) {}" không phải là operator (không quyết định thứ tự các thao tác) mà chỉ đơn thuần là 1 dấu phân cáchThe comma operator has left-to-right associativity. Two expressions separated by a comma are evaluated left to right. The left operand is always evaluated, and all side effects are completed before the right operand is evaluated.
(TOÁN TỬ ',': các biểu thức con được lượng giá theo thứ tự từ trái sang phải)
Commas can be used as separators in some contexts, such as function argument lists. Do not confuse the use of the comma as a separator with its use as an operator; the two uses are completely different.
(TOÁN TỬ ',' và dấu phân phân cách ',' là HOÀN TOÀN KHÁC NHAU)
Cám ơn bạn rox_rook đã chia xẻ (nhờ vậy tui học thêm 1 cái mới)
(hiểu biết nông cạn có gì sai sót mong dược góp ý; xin cám ơn)
-thân
Đã được chỉnh sửa lần cuối bởi bete : 30-01-2008 lúc 03:25 AM.
Tôi thấy code như thế này là đẹp rùi thân thiện nữa còn phép gán hay không thì cậu nên suy nghĩ lại cho thích hợp.Code:class Person{ private: int age; string name; public: Person(int a, const string & n) { //chú ý chỗ này là phép gán chứ không phải khởi tạo. age = a; name = n; } };
Tôi thấy age = a đâu có sao còn name = n nếu cậu ngại thì chơi luôn như vậy
name = new string(n);
OoShinHaoO
Đúng như anh nói, cái đó thực sự không sao, nhưng em nghĩ :
chỗ này thực sự là implicit conversion nó được gọi, cái đúng khởi tạo phải là như anh làm ở trên. Vấn đề thực ra em chỉ muốn làm rõ vấn đề để hiểu rõ thêm thôi, vì nhiều khi sơ ý những lỗi không đáng có như thế debug cũng trần ai lắm ạ T_T. Anyways thanhks ý kiến của anh. Lâu rùi mới thấy anh quay lại diễn đàn nhỉPHP Code:age = a;
name = n;