一、值拷贝方式
在C++中,最基本的拷贝方式就是值拷贝。当我们将一个对象赋值给另一个对象时,实际上是将原对象的值复制给新的对象。例如:


// 定义一个类
class MyClass {
public:
    int num;
};
 
int main() {
    // 创建一个对象并初始化
    MyClass obj1;
    obj1.num = 10;
 
    // 将obj1的值赋给obj2
    MyClass obj2 = obj1;
 
    // 输出obj2的值
    std::cout << obj2.num << std::endl;  // 输出结果为10
 
    return 0;
}

在上述代码中,我们创建了一个名为MyClass的类,里面有一个整型成员变量num。在主函数中,我们创建了一个obj1对象,并将其值设置为10。然后,通过将obj1的值赋给obj2,实现了拷贝。由于是值拷贝,所以obj2也被设置为10。这种方式适用于简单的数据类型或包含简单数据类型成员的类。

二、浅拷贝方式
浅拷贝是指将一个对象的成员变量逐个复制给另一个对象的成员变量,包括指针类型的成员变量。这意味着两个对象会共享同一块内存,如果其中一个对象对该内存进行修改,另一个对象的值也会发生变化。例如:


class MyString {
public:
    char* str;
};
 
int main() {
    // 创建一个对象并初始化
    MyString obj1;
    obj1.str = new char[10];
    strcpy(obj1.str, "hello");
 
    // 将obj1的值赋给obj2
    MyString obj2 = obj1;
 
    // 修改obj2的值
    obj2.str[0] = 'H';
 
    // 输出obj1和obj2的值
    std::cout << obj1.str << std::endl;  // 输出结果为Hello
    std::cout << obj2.str << std::endl;  // 输出结果为Hello
 
    return 0;
}

在上述代码中,我们定义了一个名为MyString的类,其中有一个指针类型的成员变量str,用于存储字符串。在主函数中,我们创建了一个obj1对象,并动态分配了一块内存存储字符串"hello"。然后,通过将obj1的值赋给obj2,实现了浅拷贝。由于是浅拷贝,obj2也指向了同一块内存。当我们修改obj2的值时,obj1的值也发生了变化。

三、深拷贝方式
深拷贝是指在拷贝对象时,将原对象的成员变量值复制给新对象的成员变量,并为新对象的指针类型成员变量分配新的内存。这样,两个对象将拥有相同的数据,但不共享同一块内存。例如:


class MyString {
public:
    char* str;
    // 深拷贝构造函数
    MyString(const MyString& other) {
        str = new char[strlen(other.str) + 1];
        strcpy(str, other.str);
    }
    // 析构函数
    ~MyString() {
        delete[] str;
    }
};
 
int main() {
    // 创建一个对象并初始化
    MyString obj1;
    obj1.str = new char[10];
    strcpy(obj1.str, "hello");
 
    // 将obj1的值赋给obj2
    MyString obj2 = obj1;
 
    // 修改obj2的值
    obj2.str[0] = 'H';
 
    // 输出obj1和obj2的值
    std::cout << obj1.str << std::endl;  // 输出结果为hello
    std::cout << obj2.str << std::endl;  // 输出结果为Hello
 
    return 0;
}

在上述代码中,我们为MyString类添加了一个深拷贝构造函数。在构造新对象时,我们使用了动态内存分配,为新对象的指针类型成员变量分配了新的内存,并将原对象的值复制过去。这样,当我们修改其中一个对象的值时,另一个对象的值不会受到影响。

综上所述,C++中常见的拷贝方式包括值拷贝、浅拷贝和深拷贝。我们可以根据实际情况选择适合的拷贝方式,以确保对象的正确复制和使用。