Câu hỏi Đối tượng C ++ không có mới


đây là một câu hỏi thực sự đơn giản nhưng tôi không thực hiện c ++ đúng trong nhiều năm và vì vậy tôi là một chút bối rối bởi điều này. Ngoài ra, nó không phải là điều dễ nhất (đối với tôi ít nhất) để tìm kiếm trên internet, không phải để cố gắng.

Tại sao điều này không sử dụng new từ khóa và nó hoạt động như thế nào?

Về cơ bản, những gì đang xảy ra ở đây?

CPlayer newPlayer = CPlayer(position, attacker);

51
2017-11-19 16:57


gốc




Các câu trả lời:


Biểu thức này:

CPlayer(position, attacker)

tạo một đối tượng kiểu tạm thời CPlayer sử dụng hàm tạo ở trên, sau đó:

CPlayer newPlayer =...;

Đối tượng tạm thời được đề cập được sao chép bằng cách sử dụng hàm tạo bản sao để newPlayer. Cách tốt hơn là viết những điều sau đây để tránh tạm thời:

CPlayer newPlayer(position, attacker);

44
2017-11-19 16:59



Trên thực tế trình biên dịch có lẽ sẽ tối ưu hóa nó. Trong trường hợp đó, hàm tạo bản sao sẽ không được gọi. stackoverflow.com/questions/1758142/… - BostonLogan
Một phép gán trong một khai báo không kém hiệu quả hơn việc sử dụng cú pháp hàm tạo. Nếu họ đã có những tuyên bố riêng biệt, hơn là nhận xét về thời gian sẽ là chính xác. Bản chất là điều này tuyên bố một CPlayer (thường là trên stack) hơn là phân bổ không gian cho nó từ các cửa hàng miễn phí (đống). - Adrian McCarthy
Không, gần như theo định nghĩa: Các đối tượng trên ngăn xếp chỉ sống trong khi chúng nằm trong phạm vi. stackoverflow.com/search?q=%5Bc%2B%2B%5D+stack+heap - Josh Lee
Tôi không nghĩ câu trả lời này chính xác. Mã OP nhìn giống như nó tạo ra tạm thời và sau đó sao chép nó, nhưng tiêu chuẩn 12.1.11 gợi ý khác đi. Nó chỉ là một cuộc gọi xây dựng bình thường, mà jleedev phát hiện ra. - Michael Kristofik
Nó tùy thuộc vào trình biên dịch có nên phân biệt bản sao hay không (trong trường hợp được phép). 12,8 / 15. - Steve Jessop


Ở trên xây dựng một đối tượng CPlayer trên stack, do đó nó không cần new. Bạn chỉ cần sử dụng new nếu bạn đang cố gắng phân bổ một đối tượng CPlayer trên heap. Nếu bạn đang sử dụng phân bổ heap, mã sẽ trông như thế này:

CPlayer *newPlayer = new CPlayer(position, attacker);

Lưu ý rằng trong trường hợp này, chúng ta đang sử dụng một con trỏ tới một đối tượng CPlayer sẽ cần phải được dọn sạch bằng một cuộc gọi phù hợp với delete. Một đối tượng được cấp phát trên ngăn xếp sẽ bị hủy tự động khi nó nằm ngoài phạm vi.

Trên thực tế nó đã được dễ dàng hơn và rõ ràng hơn để viết:

CPlayer newPlayer(position, attacker);

Rất nhiều trình biên dịch sẽ tối ưu hóa phiên bản mà bạn đã đăng lên ở trên và nó rõ ràng hơn để đọc.


34
2017-11-19 17:00



Tôi không nghĩ rằng điều này là chính xác: "Một đối tượng được phân bổ trên heap sẽ bị phá hủy tự động khi nó đi ra khỏi phạm vi." - Valentin
Bạn đã đúng, tôi có nghĩa là để viết "ngăn xếp", không phải "đống". Cảm ơn bạn đã chỉ ra điều này. - Timo Geusch
Đồng ý về điều này. Chúng ta nên giữ mã C ++ cùng kiểu với mã C. Vì thế CPlayer newPlayer(position, attacker); tốt hơn CPlayer newPlayer = CPlayer(position, attacker); nếu bạn muốn tạo biến ngăn xếp. - tonga


CPlayer newPlayer = CPlayer(position, attacker);

Dòng này tạo ra một đối tượng địa phương mới của kiểu CPlayer. Mặc dù xuất hiện giống như chức năng của nó, điều này đơn giản gọi là hàm tạo của CPlayer. Không có thời gian hoặc sao chép có liên quan. Đối tượng có tên newPlayer tồn tại miễn là phạm vi nó được đính kèm. Bạn không sử dụng new từ khóa ở đây vì C ++ không phải là Java.

CPlayer* newPlayer = new CPlayer(position, attacker);

Dòng này xây dựng một đối tượng CPlayer trên heap và định nghĩa một con trỏ có tên newPlayer để trỏ vào nó. Đối tượng sống cho đến khi ai đó deletes nó.


9
2017-11-19 17:40



"Không có thời gian hoặc sao chép có liên quan" - Điều này không chính xác. Không có bảo đảm như vậy. Nhưng mọi trình biên dịch đều phải bỏ qua bản sao. - sellibitze


newPlayer không có biến được cấp phát tự động mà là biến tự động được phân bổ theo stack:

CPlayer* newPlayer = new CPlayer(pos, attacker);

la khac nhau tư

CPlayer newPlayer = CPlayer(pos, attacker);

newPlayer được cấp phát trên stack thông qua lời gọi hàm lập trình CPlayer (vị trí, kẻ tấn công) bình thường, mặc dù hơi dài hơn bình thường

CPlayer newPlayer(pos, attacker);

Về cơ bản nó giống như nói:

int i = int(3);

4
2017-11-19 17:07



Cẩn thận ở đây. Đó là một "khởi tạo bản sao". nó là không phải một bài tập. - sellibitze
Tôi đứng sửa chữa, nó không phải là một nhiệm vụ; ngay cả các nhà xây dựng bản sao không có liên quan. Chỉnh sửa câu trả lời cho phù hợp. - digitalarbeiter
Chắc chắn, ctor sao chép là (ít nhất là hợp lý) tham gia. Bạn sẽ nhận thấy rằng nếu bạn làm cho bản sao của bạn ctor riêng. Sau đó, việc khởi tạo bản sao này sẽ không hoạt động nữa. Tiêu chuẩn C ++ yêu cầu một ctor sao chép có thể truy cập ngay cả khi trình biên dịch có thể tối ưu hóa bản sao. - sellibitze
không, mới phân bổ trên heap, người chơi thứ hai của bạn đang ở trên stack - Ion Todirel