Constructor giống như “hàm init”. Họ biến một đống bit tùy ý thành một vật thể sống. Tối thiểu họ khởi tạo các trường được sử dụng nội bộ. Họ cũng có thể phân bổ tài nguyên [bộ nhớ, tệp, semaphores, ổ cắm, v.v.]
“ctor” là từ viết tắt điển hình của hàm tạo
Có sự khác biệt nào giữa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
0 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
1 không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Một sự khác biệt lớn
Giả sử rằng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
2 là tên của một số lớp. Sau đó, hàm class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
3 khai báo một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
2 cục bộ có tên là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5void f[]
{
List x; // Local object named x [of class List]
// ...
}
Nhưng hàm
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
6 khai báo một hàm có tên là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7 trả về một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
2class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
0Một hàm tạo của một lớp có thể gọi một hàm tạo khác của cùng lớp để khởi tạo đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Câu trả lời dưới đây áp dụng cho C++ cổ điển [trước 11 tuổi]. bao gồm tính năng C++ 11 của các hàm tạo gọi các hàm tạo cùng loại
Không
Hãy làm một ví dụ. Giả sử bạn muốn hàm tạo của bạn
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
20 gọi một hàm tạo khác của cùng một lớp, chẳng hạn như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
21, để class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
21 đó sẽ giúp khởi tạo đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9. Thật không may, không có cách nào để làm điều này trong Classic C++Một số người làm điều đó anyway. Thật không may, nó không làm những gì họ muốn. Ví dụ, dòng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
24 không gọi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
21 trên đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9. Thay vào đó, nó gọi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
21 để khởi tạo một đối tượng cục bộ, tạm thời [không phải class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9], sau đó nó ngay lập tức hủy đối tượng tạm thời đó khi điều khiển chuyển qua class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
2Đôi khi bạn có thể kết hợp hai hàm tạo thông qua một tham số mặc định
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
3Nếu điều đó không làm việc, e. g. , nếu không có tham số mặc định phù hợp kết hợp hai hàm tạo, đôi khi bạn có thể chia sẻ mã chung của chúng trong hàm thành viên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
40 riêng tưclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5BTW KHÔNG cố gắng đạt được điều này thông qua. Một số người nghĩ rằng họ có thể nói
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
41 trong phần thân của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
20. Tuy nhiên đó là xấu, xấu, xấu. Xin đừng viết thư cho tôi và nói với tôi rằng nó dường như hoạt động trên phiên bản cụ thể của trình biên dịch cụ thể của bạn; . Những người xây dựng thực hiện một loạt những điều kỳ diệu nho nhỏ đằng sau hậu trường, nhưng kỹ thuật tồi tệ đó sẽ ảnh hưởng đến những bit được xây dựng một phần đó. Chỉ cần nói khôngCó phải hàm tạo mặc định cho class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 luôn là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
44 không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Không
Một “hàm tạo mặc định” là một hàm tạo có thể được gọi mà không có đối số. Một ví dụ về điều này là một hàm tạo không có tham số
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
0Một ví dụ khác về “hàm tạo mặc định” là một ví dụ có thể nhận các đối số, miễn là chúng được cung cấp các giá trị mặc định
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
1Hàm tạo nào được gọi khi tôi tạo một mảng gồm các đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 [ngoại trừ như được thảo luận bên dưới]class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Nếu lớp của bạn không có , bạn sẽ gặp lỗi thời gian biên dịch khi cố gắng tạo một mảng bằng cú pháp đơn giản ở trên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
2Tuy nhiên, ngay cả khi lớp của bạn đã có một hàm tạo mặc định, bạn nên cố gắng sử dụng chứ không phải là một mảng [].
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
48 cho phép bạn quyết định sử dụng bất kỳ hàm tạo nào, không chỉ hàm tạo mặc địnhclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
4Mặc dù bạn nên sử dụng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
48 thay vì một mảng, nhưng đôi khi một mảng có thể là điều nên làm và đối với những trường hợp đó, bạn có thể cần đến cú pháp “khởi tạo mảng rõ ràng”. Đây là cáchclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
00Tất nhiên, bạn không cần phải thực hiện
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
000 cho mọi mục nhập — bạn có thể nhập bất kỳ số nào bạn muốn, thậm chí cả tham số hoặc các biến khácCuối cùng, để tự khởi tạo các phần tử của mảng. Cảnh báo. no thật la xâu xi. mảng thô không thể thuộc loại
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43, vì vậy bạn sẽ cần một loạt các phép con trỏ để thực hiện những việc như tính toán các phép toán chỉ mục mảng. Cảnh báo. nó phụ thuộc vào trình biên dịch và phần cứng. bạn sẽ cần đảm bảo rằng bộ lưu trữ được căn chỉnh với sự căn chỉnh ít nhất nghiêm ngặt như yêu cầu đối với các đối tượng của lớp class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43. Cảnh báo. thật tẻ nhạt để làm cho nó an toàn ngoại lệ. bạn sẽ cần hủy các phần tử theo cách thủ công, kể cả trong trường hợp khi một ngoại lệ được ném một phần qua vòng lặp gọi hàm tạo. Nhưng nếu bạn thực sự muốn làm điều đó,. [BTW vị trí-mới là phép thuật được sử dụng bên trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
48. Sự phức tạp của việc làm đúng mọi thứ là một lý do khác để sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
48. ]Nhân tiện, tôi đã bao giờ đề cập đến điều đó chưa?
Các hàm tạo của tôi có nên sử dụng "danh sách khởi tạo" hoặc "chỉ định" không?
danh sách khởi tạo. Trên thực tế, các hàm tạo nên khởi tạo theo quy tắc tất cả các đối tượng thành viên trong danh sách khởi tạo. Một ngoại lệ được thảo luận sâu hơn
Xem không gian này để thảo luận về Khởi tạo thành viên dữ liệu không tĩnh trong C++11
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
01Xem xét hàm tạo sau khởi tạo đối tượng thành viên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006 bằng cách sử dụng danh sách khởi tạo. class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
007bất cứ điều gì_______1008. Lợi ích phổ biến nhất của việc này là cải thiện hiệu suất. Ví dụ: nếu biểu thức anything cùng loại với biến thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006, thì kết quả của biểu thức anything được tạo trực tiếp bên trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006 — trình biên dịch không tạo một bản sao riêng của đối tượng. Ngay cả khi các kiểu không giống nhau, trình biên dịch thường có thể thực hiện công việc tốt hơn với các danh sách khởi tạo so với các phép gánCách khác [không hiệu quả] để xây dựng hàm tạo là thông qua phép gán, chẳng hạn như. ________ 1011 sao cũng được ________ 1012. Trong trường hợp này, biểu thức anything sẽ tạo ra một đối tượng tạm thời, riêng biệt và đối tượng tạm thời này được chuyển vào toán tử gán của đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006. Sau đó, đối tượng tạm thời đó bị hủy tại class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29. Điều đó không hiệu quảNhư thể điều đó chưa đủ tệ, còn có một nguyên nhân khác dẫn đến sự kém hiệu quả khi sử dụng phép gán trong hàm tạo. đối tượng thành viên sẽ được xây dựng đầy đủ bởi hàm tạo mặc định của nó và điều này có thể, ví dụ, phân bổ một số lượng bộ nhớ mặc định hoặc mở một số tệp mặc định. Tất cả công việc này có thể là vô ích nếu biểu thức bất kỳ và/hoặc toán tử gán làm cho đối tượng đóng tệp đó và/hoặc giải phóng bộ nhớ đó [e. g. , nếu hàm tạo mặc định không phân bổ vùng bộ nhớ đủ lớn hoặc nếu nó mở sai tệp]
Phần kết luận. Tất cả những thứ khác đều như nhau, mã của bạn sẽ chạy nhanh hơn nếu bạn sử dụng danh sách khởi tạo thay vì gán
Ghi chú. Không có sự khác biệt về hiệu suất nếu loại
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006 là một số loại tích hợp/nội tại, chẳng hạn như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
016 hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
017 hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
018. Nhưng ngay cả trong những trường hợp này, sở thích cá nhân của tôi là đặt các thành viên dữ liệu đó trong danh sách khởi tạo thay vì thông qua chuyển nhượng để thống nhất. Một đối số đối xứng khác có lợi cho việc sử dụng danh sách khởi tạo ngay cả đối với các loại tích hợp/nội tại. class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
019 không tĩnh và các thành viên dữ liệu tham chiếu không tĩnh không thể được gán một giá trị trong hàm tạo, vì vậy để đối xứng, việc khởi tạo mọi thứ trong danh sách khởi tạo là điều hợp lýBây giờ cho các trường hợp ngoại lệ. Mọi quy tắc đều có ngoại lệ [hmmm; có phải “mọi quy tắc đều có ngoại lệ” có ngoại lệ không? Làm tôi nhớ đến Định lý Bất toàn của Gödel], và có một vài ngoại lệ đối với quy tắc “sử dụng danh sách khởi tạo”. Điểm mấu chốt là sử dụng lẽ thường. nếu nó rẻ hơn, tốt hơn, nhanh hơn, v.v. không sử dụng chúng, thì bằng mọi cách, đừng sử dụng chúng. Điều này có thể xảy ra khi lớp của bạn có hai hàm tạo cần khởi tạo các thành viên dữ liệu của đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 theo các thứ tự khác nhau. Hoặc nó có thể xảy ra khi hai thành viên dữ liệu tự tham chiếu. Hoặc khi một thành viên dữ liệu cần tham chiếu đến đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 và bạn muốn tránh cảnh báo của trình biên dịch về việc sử dụng từ khóa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 trước class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
023 bắt đầu phần thân của hàm tạo [khi trình biên dịch cụ thể của bạn tình cờ đưa ra cảnh báo cụ thể đó]. Hoặc khi bạn cần làm [tham số, toàn cầu, v.v. ] trước khi sử dụng biến đó để khởi tạo một trong các thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 của bạn. Danh sách này không đầy đủ; . Vấn đề chỉ đơn giản là thế này. sử dụng suy nghĩ thông thườngTrình khởi tạo nên được sắp xếp như thế nào trong danh sách khởi tạo của hàm tạo?
Các lớp cơ sở ngay lập tức [từ trái sang phải], sau đó là các đối tượng thành viên [từ trên xuống dưới]
Nói cách khác, thứ tự của danh sách khởi tạo phải bắt chước thứ tự khởi tạo sẽ diễn ra. Hướng dẫn này không khuyến khích một loại lỗi phụ thuộc đơn hàng đặc biệt tinh vi bằng cách đưa ra manh mối rõ ràng, trực quan. Ví dụ: phần sau chứa một lỗi ghê tởm
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
02Đầu ra của chương trình này sau
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
03Lưu ý rằng __________ 1027 được sử dụng [________ 1028] trước khi nó được khởi tạo [________ 1029]. Thay vào đó, nếu lập trình viên đã đọc và tuân theo hướng dẫn trong Câu hỏi thường gặp này, thì lỗi sẽ rõ ràng hơn. danh sách khởi tạo của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
030 sẽ đọc là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
031, cho biết trực quan rằng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
027 đã được sử dụng trước khi được khởi tạoKhông phải tất cả các trình biên dịch đều đưa ra thông báo chẩn đoán cho những trường hợp này. Bạn đã được cảnh báo
Việc một đối tượng thành viên được khởi tạo bằng cách sử dụng một đối tượng thành viên khác trong biểu thức khởi tạo có hợp lý không?
Có, nhưng hãy cẩn thận và chỉ làm điều đó khi nó tăng thêm giá trị
Trong danh sách khởi tạo của hàm tạo, cách dễ nhất và an toàn nhất là tránh sử dụng một đối tượng thành viên từ đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 trong biểu thức khởi tạo của trình khởi tạo tiếp theo cho đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9. Hướng dẫn này ngăn cảnDo hướng dẫn này, hàm tạo sau sử dụng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
035 thay vì class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
036, mặc dù chúng tương đương nhau. Tiền tố class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
037 tránh sự phụ thuộc thứ tự không cần thiết và có thể tránh đượcclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
04Một sự phụ thuộc thứ tự không cần thiết vào cách bố trí lớp của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
038 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
039 sẽ được đưa ra nếu việc khởi tạo của hàm tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
039 đã sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
036 thay vì class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
035. Tuy nhiên, sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
038 trong phần thân hàm tạo [class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
044] thì không sao. Không có phụ thuộc thứ tự nào được đưa ra vì toàn bộ danh sách khởi tạo được đảm bảo kết thúc trước khi phần thân của hàm tạo bắt đầu thực thiNếu một đối tượng thành viên phải được khởi tạo bằng một đối tượng thành viên khác thì sao?
Nhận xét tuyên bố của các thành viên dữ liệu có hiệu lực với
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
045Nếu một hàm tạo khởi tạo một đối tượng thành viên của đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 bằng cách sử dụng một đối tượng thành viên khác của đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9,. Ràng buộc bảo trì quan trọng này nên được ghi lại trong phần thân của lớpVí dụ: trong hàm tạo bên dưới, trình khởi tạo cho
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
039 sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
038 để tránh lệnh gọi thừa tới class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
050, dẫn đến phụ thuộc thứ tự trong nội dung lớpclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
05Lưu ý rằng nhận xét
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
045 được liệt kê với các thành viên dữ liệu bị ảnh hưởng trong nội dung lớp, không phải với danh sách khởi tạo hàm tạo nơi phụ thuộc thứ tự thực sự được tạo. Đó là bởi vì thứ tự của các đối tượng thành viên trong nội dung lớp là rất quan trọng;Bạn có nên sử dụng con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 trong hàm tạo không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Một số người cảm thấy bạn không nên sử dụng con trỏ
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 trong hàm tạo vì đối tượng chưa được hình thành đầy đủ. Tuy nhiên, bạn có thể sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 trong hàm tạo [trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
023bodyclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
056 và thậm chí trong ] nếu bạn cẩn thậnĐây là một cái gì đó luôn hoạt động. ____1023body
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
056 của một hàm tạo [hoặc một hàm được gọi từ hàm tạo] có thể truy cập đáng tin cậy vào các thành viên dữ liệu được khai báo trong một lớp cơ sở và/hoặc các thành viên dữ liệu được khai báo trong lớp riêng của hàm tạo. Điều này là do tất cả các thành viên dữ liệu đó được đảm bảo đã được xây dựng đầy đủ vào thời điểm ____1023bodyclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
056 của hàm khởi tạo bắt đầu thực thiĐây là một cái gì đó không bao giờ hoạt động.
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
023bodyclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
056 của hàm tạo [hoặc hàm được gọi từ hàm tạo] không thể xuống lớp dẫn xuất bằng cách gọi hàm thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
063 bị ghi đè trong lớp dẫn xuất. Nếu mục tiêu của bạn là truy cập hàm bị ghi đè trong lớp dẫn xuất,. Lưu ý rằng bạn sẽ không nhận được ghi đè trong lớp dẫn xuất độc lập với cách bạn gọi hàm thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
063. rõ ràng bằng cách sử dụng con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 [e. g. , class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
066], ngầm sử dụng con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 [e. g. , class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
068] hoặc thậm chí gọi một số hàm khác gọi hàm thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
063 trên đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 của bạn. Phía dưới là dòng này. ngay cả khi người gọi đang xây dựng một đối tượng của lớp dẫn xuất, trong quá trình khởi tạo của lớp cơ sở,. Bạn đã được cảnh báoĐây là một cái gì đó đôi khi hoạt động. nếu bạn chuyển bất kỳ thành viên dữ liệu nào trong đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 sang thành viên dữ liệu khác, bạn phải đảm bảo rằng thành viên dữ liệu khác đã được khởi tạo. Tin vui là bạn có thể xác định xem thành viên dữ liệu khác đã [hoặc chưa] được khởi tạo hay chưa bằng cách sử dụng một số quy tắc ngôn ngữ đơn giản độc lập với trình biên dịch cụ thể mà bạn đang sử dụng. Tin xấu là bạn phải biết những quy tắc ngôn ngữ đó [e. g. , các đối tượng con của lớp cơ sở được khởi tạo trước [tra cứu thứ tự nếu bạn có nhiều và/hoặc kế thừa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
063. ], thì các thành viên dữ liệu được định nghĩa trong lớp được khởi tạo theo thứ tự xuất hiện trong khai báo lớp]. Nếu bạn không biết các quy tắc này, thì đừng chuyển bất kỳ thành viên dữ liệu nào từ đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 [bất kể bạn có sử dụng từ khóa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 một cách rõ ràng hay không] cho bất kỳ thành viên dữ liệu nào khác. Và nếu bạn biết các quy tắc, hãy cẩn thận"Thành ngữ xây dựng được đặt tên" là gì?
Một kỹ thuật cung cấp các thao tác xây dựng trực quan hơn và/hoặc an toàn hơn cho người dùng thuộc lớp của bạn
Vấn đề là các hàm tạo luôn có cùng tên với lớp. Do đó, cách duy nhất để phân biệt giữa các hàm tạo khác nhau của một lớp là theo danh sách tham số. Nhưng nếu có nhiều hàm tạo, sự khác biệt giữa chúng trở nên hơi nhỏ và dễ bị lỗi
Với Thành ngữ Constructor được đặt tên, bạn khai báo tất cả các hàm tạo của lớp trong phần
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
075 hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
076 và bạn cung cấp các phương thức class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
077 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 trả về một đối tượng. Các phương thức class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 này được gọi là “Các nhà xây dựng được đặt tên. ” Nói chung, có một phương pháp class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 như vậy cho mỗi cách khác nhau để xây dựng một đối tượngVí dụ: giả sử chúng ta đang xây dựng một lớp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081 đại diện cho một vị trí trên mặt phẳng X-Y. Hóa ra có hai cách phổ biến để chỉ định tọa độ 2 không gian. tọa độ chữ nhật [X+Y], tọa độ cực [Bán kính+Góc]. [Đừng lo lắng nếu bạn không thể nhớ những điều này; vấn đề không phải là chi tiết cụ thể của các hệ tọa độ; vấn đề là có một số cách để tạo một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081. ] Thật không may, các tham số cho hai hệ tọa độ này giống nhau. hai class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
018. Điều này sẽ tạo ra một lỗi mơ hồ trong các hàm tạo quá tảiclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
06Một cách để giải quyết sự mơ hồ này là sử dụng Named Constructor Idiom
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
07Giờ đây, người dùng của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081 có một cú pháp rõ ràng và rõ ràng để tạo các class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081 trong cả hai hệ tọa độclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
08Đảm bảo rằng các hàm tạo của bạn nằm trong phần
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
076 nếu bạn muốn class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081 có các lớp dẫn xuấtThành ngữ Constructor được đặt tên cũng có thể được sử dụng để
Lưu ý rằng Thành ngữ Trình xây dựng được đặt tên, ít nhất là như đã triển khai ở trên, cũng nhanh như việc gọi trực tiếp một hàm tạo —
Trả về theo giá trị có nghĩa là có thêm bản sao và thêm chi phí không?
Không cần thiết
Tất cả [?] trình biên dịch cấp thương mại tối ưu hóa bản sao bổ sung, ít nhất là trong các trường hợp như minh họa trong
Để giữ cho ví dụ rõ ràng, hãy loại bỏ mọi thứ xuống những điều cần thiết nhất. Giả sử hàm
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089 gọi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 [“rbv” là viết tắt của “return by value”] trả về một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 theo giá trịclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
09Bây giờ câu hỏi là, Sẽ có bao nhiêu đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091? Điểm chính của Câu hỏi thường gặp này là câu trả lời là Không, trình biên dịch C++ cấp thương mại thực hiện trả về theo giá trị theo cách cho phép chúng loại bỏ chi phí hoạt động, ít nhất là trong các trường hợp đơn giản như những trường hợp được trình bày trong Câu hỏi thường gặp trước đó. Đặc biệt, tất cả [?] trình biên dịch C++ cấp thương mại sẽ tối ưu hóa trường hợp này
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
20Chắc chắn trình biên dịch được phép tạo một đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 cục bộ, tạm thời, sau đó sao chép-xây dựng đối tượng tạm thời đó vào biến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089, sau đó hủy đối tượng tạm thời đó. Nhưng tất cả [?] trình biên dịch C++ cấp thương mại sẽ không làm điều đó. câu lệnh class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
099 sẽ trực tiếp xây dựng chính class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5. Không phải là bản sao của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5, không phải là con trỏ tới class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5, không phải là tham chiếu tới class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5, mà chính là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5Bạn có thể dừng ở đây nếu bạn không thực sự muốn hiểu đoạn trước, nhưng nếu bạn muốn biết điều bí mật [ví dụ, để bạn có thể dự đoán một cách đáng tin cậy khi trình biên dịch có thể và không thể cung cấp sự tối ưu hóa đó cho bạn], thì . Khi ________ 1089 gọi ________ 1090, trình biên dịch sẽ bí mật chuyển một con trỏ đến vị trí mà _________ 1090 được cho là sẽ xây dựng đối tượng “được trả lại”. Nó có thể trông giống như thế này [nó được hiển thị dưới dạng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
208 thay vì class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
209 vì đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 chưa được tạo]class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
21Vì vậy, thành phần đầu tiên trong nước sốt bí mật là trình biên dịch [thường] chuyển đổi giá trị trả về thành chuyển qua con trỏ. Điều này có nghĩa là các trình biên dịch cấp thương mại không bận tâm đến việc tạo một. họ trực tiếp xây dựng đối tượng được trả về ở vị trí được chỉ ra bởi
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
211Thành phần thứ hai trong nước sốt bí mật là các trình biên dịch thường triển khai các hàm tạo bằng cách sử dụng một kỹ thuật tương tự. Điều này phụ thuộc vào trình biên dịch và hơi lý tưởng hóa [tôi cố ý bỏ qua cách xử lý
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
088 và quá tải], nhưng trình biên dịch thường triển khai class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
213 bằng cách sử dụng một cái gì đó như thế nàyclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
22Đặt những thứ này lại với nhau, trình biên dịch có thể triển khai câu lệnh
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
099 trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 bằng cách chuyển class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
211 làm con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 của hàm tạoclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
23Vì vậy,
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089 chuyển class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
219 đến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 và lần lượt class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 chuyển class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
219 đến hàm tạo [dưới dạng con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9]. Điều đó có nghĩa là nhà xây dựng trực tiếp xây dựng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5Vào đầu những năm 90, tôi đã tổ chức một cuộc hội thảo cho nhóm trình biên dịch của IBM ở Toronto, và một trong số các kỹ sư của họ đã nói với tôi rằng họ nhận thấy việc tối ưu hóa giá trị trả về này nhanh đến mức bạn có thể nhận được nó ngay cả khi bạn không biên dịch với tính năng tối ưu hóa đã được bật. . Bởi vì tối ưu hóa trả về theo giá trị làm cho trình biên dịch tạo ra ít mã hơn, nên nó thực sự cải thiện thời gian biên dịch ngoài việc làm cho mã được tạo của bạn nhỏ hơn và nhanh hơn. Vấn đề là tối ưu hóa lợi nhuận theo giá trị hầu như được triển khai phổ biến, ít nhất là trong các trường hợp mã như trường hợp được hiển thị ở trên
suy nghĩ cuối cùng. cuộc thảo luận này chỉ giới hạn ở việc liệu có bất kỳ bản sao bổ sung nào của đối tượng được trả về trong lệnh gọi trả về theo giá trị hay không. Đừng nhầm lẫn điều đó với những thứ khác có thể xảy ra trong
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089. Ví dụ: nếu bạn thay đổi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089 từ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
227 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
228 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
229 [lưu ý class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29 sau phần khai báo], trình biên dịch bắt buộc phải sử dụng toán tử gán của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 và trừ khi trình biên dịch có thể chứng minh rằng hàm tạo mặc định của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 theo sau là toán tử gán chính xác như . Tối ưu hóa trả về theo giá trị vẫn đóng vai trò của nó vì sẽ chỉ có một giá trị tạm thời, nhưng bằng cách thay đổi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
227 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
228 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
229, bạn đã ngăn trình biên dịch loại bỏ giá trị tạm thời cuối cùng đó.Còn việc trả về một biến cục bộ theo giá trị thì sao?
Khi mã của bạn trả về một biến cục bộ theo giá trị, trình biên dịch của bạn có thể tối ưu hóa hoàn toàn biến cục bộ - chi phí không gian bằng không và chi phí thời gian bằng không - biến cục bộ không bao giờ thực sự tồn tại như một đối tượng riêng biệt với biến mục tiêu của người gọi [xem bên dưới để biết chi tiết cụ thể . Các trình biên dịch khác không tối ưu hóa nó đi
Có vài[. ] của các trình biên dịch tối ưu hóa hoàn toàn biến cục bộ
- GNU C++ [g++] kể từ ít nhất là phiên bản 3. 3. 3
- [Những người khác cần được thêm vào; cần thêm thông tin]
Có vài[. ] của các trình biên dịch không tối ưu hóa biến cục bộ
- Microsoft Visual C ++. MẠNG 2003
- [Những người khác cần được thêm vào; cần thêm thông tin]
Đây là một ví dụ cho thấy những gì chúng tôi muốn nói trong Câu hỏi thường gặp này
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
24Câu hỏi được giải quyết trong Câu hỏi thường gặp này là. Có bao nhiêu đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 thực sự được tạo trong hệ thống thời gian chạy? . tạm thời được tạo bởi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
239, biến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 [trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090] và biến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 [trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089]. Tuy nhiên, như chúng ta đã thấy trước đó vào cùng một đối tượng, giảm tổng số đối tượng từ 3 xuống 2. Nhưng Câu hỏi thường gặp này đẩy nó thêm một bước nữa. class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 [trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090] có hiển thị dưới dạng một đối tượng thời gian chạy riêng biệt từ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 [trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089] không?Một số trình biên dịch, bao gồm nhưng không giới hạn ở những trình biên dịch được liệt kê ở trên, tối ưu hóa hoàn toàn biến cục bộ
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240. Trong các trình biên dịch đó, chỉ có một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 trong đoạn mã trên. Biến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089 hoàn toàn giống hệt đối tượng với biến của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240Họ làm điều này theo cách tương tự như được mô tả. giá trị trả về trong hàm
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 được triển khai dưới dạng truyền qua con trỏ, trong đó con trỏ trỏ đến vị trí mà đối tượng được trả về sẽ được khởi tạoVì vậy, thay vì xây dựng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 như một đối tượng cục bộ, các trình biên dịch này chỉ cần xây dựng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
258 và mỗi khi chúng thấy biến class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 được sử dụng trong mã nguồn ban đầu, chúng sẽ thay thế bằng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
258. Sau đó, dòng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
261 trở thành đơn giản là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
262 vì đối tượng được trả về đã được tạo ở vị trí được chỉ định bởi người gọiĐây là mã kết quả [giả]
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
25báo trước. tối ưu hóa này chỉ có thể được áp dụng khi tất cả các câu lệnh
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
099 của hàm trả về cùng một biến cục bộ. Nếu một câu lệnh class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
099 trong class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
090 trả về biến cục bộ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 nhưng một câu lệnh khác trả về một thứ khác, chẳng hạn như toàn cầu hoặc tạm thời, trình biên dịch không thể đặt bí danh biến cục bộ thành đích của người gọi, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5. Việc xác minh rằng tất cả các câu lệnh trả về của hàm trả về cùng một biến cục bộ đòi hỏi người viết trình biên dịch phải làm thêm công việc, đó thường là lý do tại sao một số trình biên dịch không thực hiện được việc tối ưu hóa trả về cục bộ theo giá trị đósuy nghĩ cuối cùng. cuộc thảo luận này chỉ giới hạn ở việc liệu có bất kỳ bản sao bổ sung nào của đối tượng được trả về trong lệnh gọi trả về theo giá trị hay không. Đừng nhầm lẫn điều đó với những thứ khác có thể xảy ra trong
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089. Ví dụ: nếu bạn thay đổi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
089 từ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
227 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
228 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
229 [lưu ý class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29 sau phần khai báo], trình biên dịch bắt buộc phải sử dụng toán tử gán của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 và trừ khi trình biên dịch có thể chứng minh rằng hàm tạo mặc định của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 theo sau là toán tử gán chính xác như . Tối ưu hóa trả về theo giá trị vẫn đóng vai trò của nó vì sẽ chỉ có một giá trị tạm thời, nhưng bằng cách thay đổi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
227 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
228 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
229, bạn đã ngăn trình biên dịch loại bỏ giá trị tạm thời cuối cùng đó.Tại sao tôi không thể khởi tạo dữ liệu thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 của mình trong danh sách khởi tạo của nhà xây dựng?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Bởi vì bạn phải xác định rõ ràng các thành viên dữ liệu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 của lớp mìnhclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
283class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
26class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
284 [hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
285 hoặc bất cứ thứ gì]class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
27Ghi chú. trong một số trường hợp, định nghĩa của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
286 có thể không chứa phần khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
287. Để biết chi tiết, xem vàTại sao các lớp có thành viên dữ liệu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 gặp lỗi liên kết?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Bởi vì. Nếu bạn không làm điều này, có thể bạn sẽ gặp lỗi trình liên kết
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
290. Ví dụclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
28Trình liên kết sẽ hét vào mặt bạn [
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
291] trừ khi bạn xác định [trái ngược với chỉ khai báo] class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
286 trong [chính xác] một trong các tệp nguồn của bạnclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29Vị trí thông thường để xác định thành viên dữ liệu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
294 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 là tệp class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
284 [hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
285 hoặc bất kỳ phần mở rộng tệp nguồn nào bạn sử dụng]Ghi chú. , tuy nhiên nếu bạn từng sử dụng thành viên dữ liệu, bạn vẫn cần xác định rõ ràng nó trong chính xác một đơn vị biên dịch. Trong trường hợp này, bạn không bao gồm trình khởi tạo
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
287 trong định nghĩa. bao gồm chủ đề nàyTôi có thể thêm bộ khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
287class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
29 vào phần khai báo của thành viên dữ liệu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
019 ở phạm vi lớp không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Có, mặc dù với một số lưu ý quan trọng
Trước khi xem qua các cảnh báo, đây là một ví dụ đơn giản được phép
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
30Và, , nó phải được định nghĩa chính xác trong một đơn vị biên dịch, mặc dù lần này không có phần khởi tạo
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
287class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
31Thông báo trước là bạn chỉ có thể thực hiện việc này với các kiểu tích phân hoặc kiểu liệt kê và biểu thức khởi tạo phải là một biểu thức có thể được đánh giá tại thời điểm biên dịch. nó chỉ được chứa các hằng số khác, có thể được kết hợp với các toán tử tích hợp. Ví dụ:
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
308 là biểu thức hằng số thời gian biên dịch, cũng như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
309 miễn là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
310 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
311 là hằng số thời gian biên dịch. Sau phần khai báo trên, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
312 cũng là một hằng số thời gian biên dịch. nó có thể được sử dụng trong các biểu thức hằng số thời gian biên dịch khácNếu bạn đã từng lấy địa chỉ của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
312, chẳng hạn như chuyển nó theo tham chiếu hoặc nói rõ ràng là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
314, trình biên dịch sẽ đảm bảo rằng nó có một địa chỉ duy nhất. Nếu không, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
312 thậm chí sẽ không chiếm dung lượng trong vùng dữ liệu tĩnh của quy trình của bạn"Lệnh khởi tạo ____1078 'thất bại' [sự cố]" là gì?
Một cách tinh vi để làm hỏng chương trình của bạn
Vấn đề thứ tự khởi tạo
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 là một khía cạnh rất tế nhị và thường bị hiểu sai của C++. Thật không may, nó rất khó phát hiện — lỗi thường xảy ra trước khi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
318 bắt đầuTóm lại, giả sử bạn có hai đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 tồn tại trong các tệp nguồn riêng biệt, chẳng hạn như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
322 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
323. Giả sử thêm rằng việc khởi tạo đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 [thường là hàm tạo của đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240] gọi một số phương thức trên đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5Đó là nó. Nó đơn giản mà
Phần khó khăn là bạn có 50% -50% cơ hội làm hỏng chương trình. Nếu đơn vị biên dịch cho
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
322 tình cờ được khởi tạo trước, thì tất cả đều ổn. Nhưng nếu đơn vị biên dịch cho class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
323 được khởi tạo trước, thì quá trình khởi tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 sẽ được chạy trước quá trình khởi tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 và bạn đã nâng cốc chúc mừng. e. g. , Hàm tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 có thể gọi một phương thức trên đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5, nhưng đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 vẫn chưa được tạoĐể biết cách giải quyết vấn đề, hãy xem
Ghi chú. Vấn đề thứ tự khởi tạo tĩnh cũng có thể áp dụng cho các loại tích hợp/nội tại
Làm cách nào để ngăn chặn “sự cố thứ tự khởi tạo ____1078”?
Để ngăn , hãy sử dụng Thành ngữ Xây dựng khi sử dụng lần đầu, được mô tả bên dưới
Ý tưởng cơ bản của Thành ngữ Xây dựng khi sử dụng lần đầu là bọc đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 của bạn bên trong một hàm. Ví dụ: giả sử bạn có hai lớp, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
337. Có một đối tượng namespace-scope/global class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 được gọi là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5, và một namespace-scope/global class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
337 object được gọi là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240. Hàm tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
337 gọi phương thức class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
343 trên đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5. Tệp class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
322 định nghĩa đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
32Tệp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
323 định nghĩa đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
33Để hoàn thiện, hàm tạo
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
337 có thể trông giống như thế nàyclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
34Bạn sẽ có một nếu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 được xây dựng trước class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5. Như đã viết ở trên, thảm họa này sẽ xảy ra khoảng 50% thời gian, vì hai đối tượng được khai báo trong các tệp nguồn khác nhau và các tệp nguồn đó không đưa ra gợi ý nào cho trình biên dịch hoặc trình liên kết về thứ tự khởi tạo tĩnhCó nhiều giải pháp cho vấn đề này, nhưng một giải pháp rất đơn giản và hoàn toàn di động là Thành ngữ Xây dựng khi sử dụng lần đầu. thay thế đối tượng namespace-scope/global
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 bằng namespace-scope/hàm toàn cầu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7 trả về đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 theo tham chiếuclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
35Vì các đối tượng cục bộ
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 được xây dựng lần đầu tiên luồng điều khiển qua khai báo của chúng [chỉ], nên câu lệnh class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
358 ở trên sẽ chỉ xảy ra một lần. lần đầu tiên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7 được gọi. Mọi cuộc gọi tiếp theo sẽ trả về cùng một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 [đối tượng được chỉ định bởi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361]. Sau đó, tất cả những gì bạn làm là thay đổi cách sử dụng của bạn từ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
36Đây được gọi là Thành ngữ xây dựng khi sử dụng lần đầu bởi vì nó chỉ làm được điều đó. đối tượng [phạm vi không gian tên hợp lý / toàn cầu]
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 được xây dựng trong lần sử dụng đầu tiênNhược điểm của phương pháp này là đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 không bao giờ bị hủy. Nếu đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 có một hàm hủy với các tác dụng phụ quan trọng, thì đó là câu trả lời cho mối quan tâm này; Ghi chú. Vấn đề thứ tự khởi tạo tĩnh cũng có thể áp dụng cho các loại tích hợp/nội tại
Tại sao Thành ngữ Xây dựng khi sử dụng lần đầu không sử dụng đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 thay vì con trỏ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Câu trả lời ngắn. có thể sử dụng một đối tượng tĩnh, nhưng làm như vậy sẽ mở ra một vấn đề khác [tinh vi không kém, khó chịu không kém]
Câu trả lời dài. đôi khi mọi người lo lắng về thực tế là “rò rỉ. ” Trong nhiều trường hợp, đây không phải là vấn đề, nhưng nó lại là vấn đề trong một số trường hợp. Ghi chú. mặc dù đối tượng được chỉ ra bởi
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 trong Câu hỏi thường gặp trước đó không bao giờ bị xóa, bộ nhớ không thực sự bị "rò rỉ" khi chương trình thoát do hệ điều hành tự động lấy lại tất cả bộ nhớ trong đống của chương trình khi chương trình đó thoát. Nói cách khác, lần duy nhất bạn cần lo lắng về điều này là khi hàm hủy của đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 thực hiện một số hành động quan trọng [chẳng hạn như ghi nội dung nào đó vào tệp] đôi khi phải xảy ra trong khi chương trình đang thoátTrong những trường hợp mà đối tượng xây dựng trên lần sử dụng đầu tiên [trong trường hợp này là
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43] cuối cùng cần phải bị hủy, bạn có thể cân nhắc thay đổi chức năng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7 như sauclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
37Tuy nhiên, có [hay đúng hơn là có thể có] một vấn đề khá tế nhị với sự thay đổi này. Để hiểu vấn đề tiềm ẩn này, hãy nhớ tại sao chúng ta lại làm tất cả những điều này ngay từ đầu. chúng tôi cần đảm bảo 100% đối tượng tĩnh của chúng tôi [a] được xây dựng trước lần sử dụng đầu tiên và [b] không bị hủy cho đến sau lần sử dụng cuối cùng. Rõ ràng sẽ là một thảm họa nếu bất kỳ đối tượng tĩnh nào được sử dụng trước khi xây dựng hoặc sau khi phá hủy. Thông báo ở đây là bạn cần phải lo lắng về hai tình huống [khởi tạo tĩnh và khử khởi tạo tĩnh], không chỉ một
Bằng cách thay đổi khai báo từ
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
373 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
374, chúng tôi vẫn xử lý chính xác tình huống khởi tạo nhưng chúng tôi không còn xử lý tình huống khử khởi tạo nữa. Ví dụ: nếu có 3 đối tượng tĩnh, chẳng hạn như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
310, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
311 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
377, sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 trong quá trình hủy của chúng, thì cách duy nhất để tránh thảm họa khử khởi tạo tĩnh là nếu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 bị hủy sau cả ba đối tượngđiểm là đơn giản. nếu có bất kỳ đối tượng tĩnh nào khác mà trình hủy của chúng có thể sử dụng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 sau khi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 bị hủy, bang, bạn chết. Nếu các hàm tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
310, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
311 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
377 sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361, thông thường bạn sẽ ổn vì hệ thống thời gian chạy sẽ, trong quá trình khử khởi tạo tĩnh, hủy class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 sau khi đối tượng cuối cùng trong số ba đối tượng đó bị hủy. Tuy nhiên, nếu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
310 và/hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
311 và/hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
377 không sử dụng được class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 trong hàm tạo của chúng và/hoặc nếu bất kỳ mã nào ở bất kỳ đâu lấy được địa chỉ của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
361 và trao nó cho một số đối tượng tĩnh khác, thì mọi khả năng đặt cược đều bị tắt và bạn phải rất, Có, nhưng nó có các chi phí không nhỏ khác
Kỹ thuật đảm bảo cả khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 và khử khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 là gì?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Câu trả lời ngắn. sử dụng Thành ngữ Bộ đếm tiện lợi [nhưng đảm bảo rằng bạn hiểu sự đánh đổi không tầm thường. ]
Động lực
- Việc sử dụng một con trỏ và cố ý làm rò rỉ đối tượng. Điều đó thường vô hại, vì hệ điều hành thường sẽ dọn sạch bộ nhớ của một tiến trình khi tiến trình kết thúc. Tuy nhiên, nếu đối tượng có một hàm hủy không tầm thường với các tác dụng phụ quan trọng, chẳng hạn như ghi vào tệp hoặc một số hành động không bay hơi khác, thì bạn cần thêm
- Đó là nơi đến. nó không làm rò rỉ đối tượng, nhưng nó không kiểm soát thứ tự khử khởi tạo tĩnh, do đó [rất. ] không an toàn khi sử dụng đối tượng trong quá trình khử khởi tạo tĩnh, nghĩa là từ một hàm hủy của một đối tượng được khai báo tĩnh khác
- Nếu bạn cần kiểm soát thứ tự của cả khởi tạo tĩnh và khử khởi tạo tĩnh, nghĩa là nếu bạn muốn truy cập một đối tượng được cấp phát tĩnh từ cả hàm tạo và hàm hủy của các đối tượng tĩnh khác, thì hãy tiếp tục đọc
- Nếu không thì chạy đi
LÀM. VIẾT NÀY LÊN
LÀM. VIẾT LÊN CÁC GIAO DỊCH - bây giờ bạn đã biết cách sử dụng Thành ngữ Bộ đếm tiện lợi, hãy chắc chắn rằng bạn hiểu cả thời điểm và [đặc biệt là. ] khi không sử dụng. Một kích thước không phù hợp với tất cả
Làm cách nào để ngăn chặn “sự cố thứ tự khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078” cho các thành viên dữ liệu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 của tôi?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Sử dụng Thành ngữ cấu trúc khi sử dụng lần đầu, về cơ bản giống như , hoặc có lẽ , nhưng nó sử dụng hàm thành viên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 thay vì hàm phạm vi không gian tên/hàm toàn cầuGiả sử bạn có một lớp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
397 có một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
38Đương nhiên, thành viên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 này được khởi tạo riêngclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
39Đương nhiên, đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 cũng sẽ được sử dụng trong một hoặc nhiều phương thức của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
397class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
50Nhưng bây giờ “kịch bản thảm họa” là nếu ai đó ở đâu đó gọi phương thức này trước khi đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
43 được xây dựng. Ví dụ: nếu người khác tạo một đối tượng tĩnh class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
397 và gọi phương thức class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
505 của nó trong quá trình khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078, thì bạn sẽ phụ thuộc vào trình biên dịch về việc liệu trình biên dịch sẽ xây dựng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
507 trước hay sau khi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
505 được gọi. [Lưu ý rằng ủy ban ANSI/ISO C++ đang giải quyết vấn đề này, nhưng trình biên dịch vẫn chưa có sẵn để xử lý những thay đổi này; hãy theo dõi không gian này để cập nhật trong tương lai. ]Trong mọi trường hợp, việc thay đổi thành viên dữ liệu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
507 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 thành hàm thành viên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 luôn có thể di động và an toànclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
51Đương nhiên, thành viên
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 này được khởi tạo riêngclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
52Sau đó, bạn chỉ cần thay đổi bất kỳ cách sử dụng nào của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
7class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
53Nếu bạn siêu nhạy cảm với hiệu suất và bạn lo lắng về chi phí hoạt động của một lệnh gọi chức năng bổ sung trên mỗi lệnh gọi của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
515, bạn có thể thiết lập một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
517 để thay thế. Như bạn nhớ lại, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078 cục bộ chỉ được khởi tạo một lần [lần đầu tiên kiểm soát chảy qua khai báo của chúng], vì vậy điều này sẽ chỉ gọi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
519 một lần. lần đầu tiên class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
515 được gọiclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
54Ghi chú. Vấn đề thứ tự khởi tạo tĩnh cũng có thể áp dụng cho các loại tích hợp/nội tại
Tôi có cần lo lắng về “vấn đề thứ tự khởi tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
078” đối với các biến thuộc loại tích hợp/nội tại không?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Đúng
Nếu bạn khởi tạo kiểu tích hợp/nội tại của mình bằng cách sử dụng lệnh gọi hàm, vấn đề thứ tự khởi tạo tĩnh có thể giết bạn cũng tệ như với các kiểu do người dùng định nghĩa/lớp. Ví dụ: đoạn mã sau hiển thị lỗi
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
55Đầu ra của chương trình nhỏ này sẽ cho thấy rằng nó sử dụng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 trước khi khởi tạo nó. Giải pháp, như trước đây, làclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
56Tất nhiên, bạn có thể đơn giản hóa việc này bằng cách di chuyển mã khởi tạo cho
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 vào các chức năng tương ứng của chúngclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
57Và, nếu bạn có thể loại bỏ các câu lệnh in, bạn có thể đơn giản hóa chúng thành một thứ thực sự đơn giản
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
58Hơn nữa, vì
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
240 được khởi tạo bằng một biểu thức hằng, nên nó không còn cần hàm bao bọc nữa — nó có thể lại là một biến đơn giảnLàm cách nào tôi có thể xử lý một hàm tạo không thành công?
Ném một ngoại lệ. Để biết chi tiết, xem
"Thành ngữ tham số được đặt tên" là gì?
Đó là một cách khá hữu ích để khai thác
Vấn đề cơ bản được giải quyết bởi Thành ngữ tham số được đặt tên là C++ chỉ hỗ trợ các tham số vị trí. Ví dụ: người gọi hàm không được phép nói, “Đây là giá trị cho tham số chính thức
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
526 và thứ khác này là giá trị cho tham số chính thức class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
527. ” Tất cả những gì bạn có thể làm trong C++ [và C và Java] là nói, “Đây là tham số đầu tiên, đây là tham số thứ hai, v.v. ” Phương án thay thế, được gọi là các tham số được đặt tên và được triển khai bằng ngôn ngữ Ada, đặc biệt hữu ích nếu một hàm nhận một số lượng lớn các tham số hầu hết có thể mặc địnhTrong nhiều năm, mọi người đã đưa ra rất nhiều cách giải quyết cho việc thiếu các tham số được đặt tên trong C và C++. Một trong số đó liên quan đến việc chôn các giá trị tham số trong một tham số chuỗi sau đó phân tích cú pháp chuỗi này trong thời gian chạy. Đây là những gì được thực hiện trong tham số thứ hai của
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
528, ví dụ. Một cách giải quyết khác là kết hợp tất cả các tham số boolean trong một bản đồ bit, sau đó hàm gọi hoặc một loạt các hằng số được dịch chuyển bit lại với nhau để tạo ra tham số thực tế. Đây là những gì được thực hiện trong tham số thứ hai của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
529, ví dụ. Những cách tiếp cận này hoạt động, nhưng kỹ thuật sau đây tạo ra mã người gọi rõ ràng hơn, dễ viết hơn, dễ đọc hơn và nói chung là thanh lịch hơnÝ tưởng, được gọi là Thành ngữ tham số được đặt tên, là thay đổi các tham số của hàm thành các phương thức của một lớp mới được tạo, trong đó tất cả các phương thức này trả về
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
530 theo tham chiếu. Sau đó, bạn chỉ cần đổi tên hàm chính thành một phương thức “do-it” không tham số trên lớp đóChúng tôi sẽ làm một ví dụ để làm cho đoạn trước dễ hiểu hơn
Ví dụ sẽ dành cho khái niệm “mở tệp”. Giả sử khái niệm đó yêu cầu một cách hợp lý một tham số cho tên của tệp và tùy ý cho phép các tham số để biết liệu tệp có nên được mở ở chế độ chỉ đọc hay không. đọc ghi vs. chỉ ghi, tệp có nên được tạo hay không nếu nó chưa tồn tại, vị trí ghi nên ở cuối [“chắp thêm”] hay ở đầu [“ghi đè”], kích thước khối nếu tệp . quyền truy cập độc quyền và có thể là một số quyền truy cập khác. Nếu chúng tôi triển khai khái niệm này bằng cách sử dụng một hàm bình thường với các tham số vị trí, mã người gọi sẽ rất khó đọc. sẽ có tới 8 tham số vị trí và người gọi có thể sẽ mắc nhiều lỗi. Vì vậy, thay vào đó chúng tôi sử dụng Thành ngữ tham số được đặt tên
Trước khi chúng tôi thực hiện triển khai, đây là mã trình gọi có thể trông như thế nào, giả sử bạn sẵn sàng chấp nhận tất cả các tham số mặc định của hàm
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
59Đó là trường hợp dễ dàng. Bây giờ, đây là giao diện nếu bạn muốn thay đổi một loạt các tham số
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
00Lưu ý cách các “tham số”, nếu gọi chúng như vậy là hợp lý, sắp xếp theo thứ tự ngẫu nhiên [chúng không theo vị trí] và tất cả chúng đều có tên. Vì vậy, lập trình viên không cần phải nhớ thứ tự của các tham số và tên [hy vọng] rõ ràng
Vì vậy, đây là cách thực hiện nó. trước tiên, chúng tôi tạo một lớp [
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
531] chứa tất cả các giá trị tham số dưới dạng thành viên dữ liệu class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
075. Các tham số bắt buộc [trong trường hợp này, tham số bắt buộc duy nhất là tên tệp] được triển khai như một tham số vị trí bình thường trên hàm tạo của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
531, nhưng hàm tạo đó không thực sự mở tệp. Sau đó, tất cả các tham số tùy chọn [chỉ đọc so với. đọc ghi, v.v. ] trở thành các phương thức. Các phương pháp này [e. g. , class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
534, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
535, v.v. ] trả về một tham chiếu đến đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
9 của chúng để các lệnh gọi phương thức có thể đượcclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
01Điều khác duy nhất cần làm là tạo hàm tạo cho lớp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
537 để lấy một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
531class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
02Hàm tạo này nhận các tham số thực tế từ đối tượng OpenFile, sau đó thực sự mở tệp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
03Lưu ý rằng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
531 tuyên bố class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
537 là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
541 của nó, theo cách đóVì mỗi hàm thành viên trong chuỗi trả về một tham chiếu nên không có sự sao chép đối tượng và chuỗi có hiệu quả cao. Hơn nữa, nếu các hàm thành viên khác nhau là
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
544, thì mã đối tượng được tạo có thể sẽ ngang bằng với mã kiểu C đặt các thành viên khác nhau của một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
545. Tất nhiên, nếu các chức năng thành viên không phải là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
544, thì có thể có một chút tăng kích thước mã và giảm một chút hiệu suất [nhưng chỉ khi quá trình xây dựng xảy ra trên đường dẫn quan trọng của chương trình gắn với CPU; đây là một hộp sâu I Tại sao tôi gặp lỗi sau khi khai báo đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 qua class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
548?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Bởi vì điều đó không tạo ra một đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 - nó khai báo một hàm không phải thành viên trả về một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091. Thuật ngữ “Most Vexing Parse” được đặt ra bởi Scott Myers để mô tả tình huống nàyĐiều này thực sự sẽ gây tổn thương;
Đầu tiên, đây là một lời giải thích tốt hơn về vấn đề. Giả sử có một lớp tên là
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
551 có một ctor mặc định. Đây thậm chí có thể là một lớp thư viện chẳng hạn như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
552, nhưng bây giờ chúng ta sẽ chỉ gọi nó là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
551class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
04Bây giờ, giả sử có một lớp khác tên là
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 có một diễn viên lấy một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
551. Như trước đây, điều này có thể được xác định bởi một người khác ngoài bạnclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
05Bây giờ bạn muốn tạo một đối tượng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 bằng cách sử dụng một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
551 tạm thời. Nói cách khác, bạn muốn tạo một đối tượng thông qua class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
558 và chuyển đối tượng đó tới ctor class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 để tạo một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 cục bộ có tên là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
06Đó là một câu chuyện dài, nhưng có một giải pháp [hy vọng bạn đang ngồi xuống. ] là thêm một cặp
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
562 xung quanh phần class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
558class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
07Một giải pháp khác là sử dụng
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
287 trong phần khai báo của bạn [xem bản in đẹp bên dưới]class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
08Ghi chú. Giải pháp trên yêu cầu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
565 để có thể truy cập hàm tạo bản sao class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091. Trong hầu hết các tình huống, điều đó có nghĩa là trình tạo bản sao của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 cần phải là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
077, mặc dù nó không cần phải là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
077 trong trường hợp ít phổ biến hơn khi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
565 là bạn của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
571. Nếu bạn không chắc điều đó có nghĩa là gì, hãy thử. nếu mã của bạn biên dịch, bạn đã vượt qua bài kiểm traĐây là một giải pháp khác [bản in đẹp hơn bên dưới]
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
09Ghi chú. Từ "thường" ở trên có nghĩa là điều này. điều trên chỉ thất bại khi
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
572 hoặc khi không thể truy cập trình tạo bản sao của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 [thường khi đó là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
075 hoặc class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
076 và mã của bạn không phải là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
541]. Nếu bạn không chắc điều đó có nghĩa là gì, hãy dành 60 giây và biên dịch nó. Bạn được đảm bảo tìm hiểu xem nó có hoạt động hay không trong thời gian biên dịch, vì vậy nếu nó được biên dịch rõ ràng, nó sẽ hoạt động trong thời gian chạyTuy nhiên, giải pháp tốt nhất, việc tạo ra giải pháp này ít nhất được thúc đẩy một phần bởi thực tế là Câu hỏi thường gặp này tồn tại, là sử dụng , thay thế
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
562 xung quanh cuộc gọi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
558 bằng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
580 thay thếclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
10Đó là kết thúc của các giải pháp; . Khi trình biên dịch nhìn thấy
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
548, nó nghĩ rằng phần class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
558 đang khai báo một hàm không phải thành viên trả về một đối tượng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
551, vì vậy nó nghĩ rằng bạn đang khai báo sự tồn tại của một hàm gọi là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
5 trả về một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 và nhận một tham số duy nhất của . ”Bây giờ đây là phần buồn. Trên thực tế, nó thật thảm hại. Một số máy bay không người lái không suy nghĩ ngoài kia sẽ bỏ qua đoạn cuối cùng đó, sau đó họ sẽ áp đặt một tiêu chuẩn viết mã ngu ngốc, không chính xác, không liên quan và đơn giản có nội dung như: “Không bao giờ tạo tạm thời bằng cách sử dụng hàm tạo mặc định” hoặc “Luôn luôn . Nếu đó là bạn, hãy tự bắn mình trước khi gây thêm sát thương. Những người không hiểu vấn đề không nên nói cho người khác cách giải quyết. harp
[Đó chủ yếu là lưỡi trong má. Nhưng có một hạt sự thật trong đó. Vấn đề thực sự là mọi người có xu hướng tôn thờ sự nhất quán và họ có xu hướng ngoại suy từ những điều tối nghĩa đến những điều phổ biến. Điều đó không khôn ngoan. ]
Mục đích của từ khóa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573 là gì?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
Từ khóa
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573 là một trang trí tùy chọn cho các hàm tạo và toán tử chuyển đổi để báo cho trình biên dịch biết rằng một hàm tạo hoặc toán tử chuyển đổi nhất định có thể không được sử dụng để chuyển một biểu thức sang loại lớp của nóVí dụ: không có từ khóa
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573, đoạn mã sau là hợp lệclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
11Nhưng đôi khi bạn muốn ngăn chặn loại quảng cáo ngầm hoặc chuyển đổi loại ngầm này. Ví dụ: nếu
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 thực sự là một vùng chứa dạng mảng và 42 là kích thước ban đầu, bạn có thể muốn cho phép người dùng của mình nói, class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
592 hoặc có thể là class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
593, nhưng không chỉ class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
594. Nếu đúng như vậy, bạn nên sử dụng từ khóa class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
12Bạn có thể kết hợp các hàm tạo
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573 và không phải ____2573 và các toán tử chuyển đổi trong cùng một lớp. Ví dụ: lớp này có một hàm tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573 lấy một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
599 nhưng một hàm tạo không phải class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573 lấy một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
001 và có thể được chuyển đổi hoàn toàn thành gấp đôi, nhưng chỉ được chuyển đổi rõ ràng thành boolclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
13Đoạn mã trên sẽ in như sau
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
14Biến
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
310 được khởi tạo bằng cách sử dụng hàm tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
003 vì không thể sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
004 trong cách truyền ngầm định, nhưng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
005 có thể được hiểu là một class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
006, nghĩa là, như class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
007 và được chuyển đổi ngầm định sang class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
091 bằng cách sử dụng class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
009. Đây có thể hoặc không phải là những gì bạn dự định, nhưng đây là những gì xảy raTại sao hàm tạo của tôi không hoạt động bình thường?
Đây là một câu hỏi có nhiều dạng. Như là
- Tại sao trình biên dịch sao chép các đối tượng của tôi khi tôi không muốn?
- Làm cách nào để tắt sao chép?
- Làm cách nào để ngừng chuyển đổi ngầm định?
- Làm thế nào mà int của tôi biến thành một số phức?
Theo mặc định, một lớp được cung cấp một hàm tạo sao chép và một phép gán sao chép sao chép tất cả các phần tử, một hàm tạo di chuyển và một phép gán di chuyển sẽ di chuyển tất cả các phần tử. Ví dụ
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
15Ở đây chúng tôi nhận được
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
010 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
011. Đó thường chính xác là những gì bạn muốn [và cần thiết cho khả năng tương thích với C], nhưng hãy cân nhắcclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
16Ở đây, bản sao mặc định cung cấp cho chúng tôi
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
012 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
013. Điều này dẫn đến thảm họa. khi chúng tôi thoát khỏi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
3, hàm hủy cho class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
015 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
016 được gọi và đối tượng được trỏ bởi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
017 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
018 bị xóa hai lầnLàm thế nào để chúng ta tránh điều này?
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
17Nếu chúng ta cần sao chép hoặc di chuyển, tất nhiên chúng ta có thể xác định các bộ khởi tạo và phép gán thích hợp để cung cấp ngữ nghĩa mong muốn
Bây giờ quay lại
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081. Đối với class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
081, ngữ nghĩa sao chép mặc định vẫn ổn, vấn đề là hàm tạoclass Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
18Mọi người cung cấp các đối số mặc định để có được sự tiện lợi được sử dụng cho
class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
021 và class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
022. Sau đó, một số ngạc nhiên bởi việc chuyển đổi class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
023 thành class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
024 trong cuộc gọi của class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
3. Hàm tạo này xác định một chuyển đổi. Theo mặc định, đó là một chuyển đổi ngầm. Để yêu cầu chuyển đổi rõ ràng như vậy, hãy khai báo hàm tạo class Fred {
public:
Fred[];
// ...
};
int main[]
{
Fred a[10]; // Calls the default constructor 10 times
Fred* p = new Fred[10]; // Calls the default constructor 10 times
// ...
}
573