C++中如何用拷贝构造函数实现Yahtzee类跨类双指针的深拷贝?
Hey there! Let's break down how to handle that double pointer to your Protocol class in the Yahtzee copy constructor—since you already have the Dice dynamic array sorted, half the battle is won.
First, let's clarify: when you say "double pointer," I’m assuming you mean a Protocol** member in your Yahtzee class. This usually falls into two common use cases, so I’ll walk through both, plus key pitfalls to avoid.
First, Let’s Set the Stage (Assumed Class Structure)
I’ll start with a rough outline of what your Yahtzee class might look like, to ground the examples:
class Yahtzee { private: Protocol** protocol_ptr; // Your double pointer Dice* dice_array; // Dynamic array you’ve already handled int dice_count; // Size of the Dice array int protocol_count; // Only needed if protocol_ptr is an array (case 2) public: // Regular constructor (example) Yahtzee(int num_dice, int num_protocols = 1) { // Initialize Dice array (your working logic) dice_count = num_dice; dice_array = new Dice[dice_count]; // Example init for protocol_ptr (adjust based on your actual code) // Case 1: Single Protocol object (pointer to pointer) protocol_ptr = new Protocol*; *protocol_ptr = new Protocol(); // OR Case 2: Dynamic array of Protocol objects // protocol_ptr = new Protocol*[num_protocols]; // for (int i = 0; i < num_protocols; ++i) { // protocol_ptr[i] = new Protocol(); // } // protocol_count = num_protocols; } // Destructor (critical to avoid leaks/memory issues) ~Yahtzee() { // Clean up Dice array delete[] dice_array; // Clean up protocol_ptr (match your constructor logic!) // Case 1: Single object delete *protocol_ptr; delete protocol_ptr; // OR Case 2: Array of objects // for (int i = 0; i < protocol_count; ++i) { // delete protocol_ptr[i]; // } // delete[] protocol_ptr; } // Your target: Copy Constructor Yahtzee(const Yahtzee& other); };
Case 1: Double Pointer Points to a Single Protocol Object
If protocol_ptr is just a pointer to a single Protocol* (e.g., you use it to manage a resettable Protocol instance), your copy constructor needs to perform a deep copy at both levels:
- Allocate a new
Protocol*container. - Allocate a new
Protocolinstance, copying the data from the original object’sProtocol.
Here’s the code:
Yahtzee::Yahtzee(const Yahtzee& other) { // First, copy your Dice array (your existing working logic) dice_count = other.dice_count; dice_array = new Dice[dice_count]; for (int i = 0; i < dice_count; ++i) { dice_array[i] = other.dice_array[i]; // Assumes Dice has a valid copy constructor } // Now handle the double pointer to a single Protocol // Step 1: Allocate a new pointer to hold the Protocol* protocol_ptr = new Protocol*; // Step 2: Deep copy the Protocol object itself (uses Protocol's copy constructor) *protocol_ptr = new Protocol(*(other.protocol_ptr)); }
Case 2: Double Pointer is a Dynamic Array of Protocol Objects
If protocol_ptr points to an array of Protocol* instances (e.g., multiple Protocol objects managed by Yahtzee), you’ll need to:
- Copy the array size from the original object.
- Allocate a new array of
Protocol*. - Iterate through the original array, deep copying each
Protocolinstance.
Here’s how that looks:
Yahtzee::Yahtzee(const Yahtzee& other) { // Copy Dice array (your existing logic) dice_count = other.dice_count; dice_array = new Dice[dice_count]; for (int i = 0; i < dice_count; ++i) { dice_array[i] = other.dice_array[i]; } // Copy the Protocol array (double pointer) protocol_count = other.protocol_count; // Step 1: Allocate a new array of Protocol* protocol_ptr = new Protocol*[protocol_count]; // Step 2: Deep copy each Protocol object in the array for (int i = 0; i < protocol_count; ++i) { protocol_ptr[i] = new Protocol(*(other.protocol_ptr[i])); } }
Critical Things to Remember
ProtocolMust Have a Valid Copy Constructor
IfProtocolitself uses dynamic memory (e.g., its own pointers, arrays), you need to write a deep copy constructor forProtocoltoo. Relying on the compiler-generated one will do a shallow copy, leading to shared resources and crashes when objects are destroyed.Match Destructor Logic to Copy Constructor
The way you clean upprotocol_ptrin the destructor must exactly match how you allocated it in the constructor and copy constructor. Mismatchingdeletevsdelete[]or skipping a level of deletion will cause memory leaks or double-free errors.Avoid Shallow Copy Traps
Never just assignprotocol_ptr = other.protocol_ptr—this makes bothYahtzeeobjects share the same underlyingProtocolmemory. When one object is destroyed, it’ll free that memory, leaving the other with a dangling pointer (undefined behavior!).Consider Smart Pointers for Easier Management
If you’re using C++11 or later, swap raw pointers forstd::unique_ptrorstd::shared_ptrto avoid manual memory management. For example:- Replace
Protocol**(single object) withstd::unique_ptr<std::unique_ptr<Protocol>> - Replace
Protocol**(array) withstd::vector<std::unique_ptr<Protocol>>
Smart pointers handle copying/moving and destruction automatically, reducing the chance of mistakes.
- Replace
内容的提问来源于stack exchange,提问作者PumpkinSteph

