为什么操作符 + - * / 返回值应该为const

class CAClass
{
    
public:
    
    CAClass(int i): m_i(i)
    {
        
    }
    
    // 需要注意返回值为const
    const CAClass operator* (const CAClass &a)
    {
        return CAClass(a.m_i * m_i);
    }
    
    // 需要做连等 a = b = c
    CAClass& operator= (const CAClass& a)
    {
        if (&a == this)
            return *this;
        
        m_i = a.m_i;
        
        return *this;
    }
    
    bool operator== (const CAClass& a)
    {
        return m_i == a.m_i;
    }
    
    // 常对象进行比较
    bool operator== (const CAClass& a) const
    {
        return m_i == a.m_i;
    }
    
private:
    
    int m_i;
    
};


在这里重载的operator *返回值为 const 原因是: 避免下面代码的错误


    CAClass a(1), b(2);
    CAClass c(2);
    
    if (a * b = c)
    {
        std::cout << "a 和 b相等" << std::endl;
    }

其实是想比较大小,但是少些了一个=,在内置类型的时候编译器会报错,所以我们需要遵循内置类型的原则,返回const 就可以避免这类错误的发生

在CAClass类中我们需要注意:

1. operator* 操作符重载返回值是const

2. operator= 操作符重载返回值是引用,非常引用,因为需要满足等号连等的需求

3. operator==操作符重栽函数发生了重载,主要是因为operator*这类的操作返回值是常对象,所以只能调用常成员函数!


<think>题目要求我们完成一个函数`bulk_mem_copy`,并补充返回值,同时编写测试函数和main函数。 函数功能:实现内存拷贝,并处理源地址和目标地址重叠的情况(重叠时从后向前拷贝以避免覆盖)。另外,为了提高效率,在非重叠情况下,使用`unsigned long`(通常为4或8字节)的长度进行拷贝,然后再拷贝剩余的字节。 根据函数逻辑,如果拷贝成功,我们应该返回什么呢?通常,内存拷贝函数如`memcpy`返回目标指针,而`memmove`也是返回目标指针。但观察函数原型,返回类型是`int`,并且当参数不合法时返回-1。因此,我们可能需要返回一个表示成功拷贝的字节数,或者返回0表示成功,非0表示失败。但原函数在参数不合法时返回-1,在拷贝完成后应该返回什么呢? 注意:函数在参数不合法时返回-1,那么正常拷贝时应该返回什么?我们可以返回实际拷贝的字节数,即len。因为如果拷贝成功,就是拷贝了len个字节。所以,在函数最后,我们返回len。 因此,在函数最后添加:`return len;` 接下来,我们需要编写测试函数,使用assert进行测试,并编写main函数使其可以正式交互(例如,可以选择运行测试或手动输入测试)。 测试用例应该包括: 1. 正常情况(不重叠) 2. 目标地址在源地址中间(重叠,且需要从后向前拷贝) 3. 源地址在目标地址中间(重叠,但此时不需要从后向前拷贝,因为不会覆盖未拷贝的数据?实际上,根据我们的判断条件,只有from < to 且 to < from+len 时才需要从后向前拷贝。所以另一种重叠情况(to在from之前)不会进入这个分支,而是正常拷贝,这样也不会覆盖,因为拷贝方向是从前往后,而目标在源之前,所以不会覆盖源中未拷贝的部分) 4. 参数不合法的情况(to为NULL,from为NULL,len<=0) 注意:在重叠情况下,我们分两种情况:一种是目标地址在源地址的范围内(即from < to < from+len),此时需要从后向前拷贝;另一种是目标地址在源地址之前(to <= from)或者目标地址在源地址之后(to >= from+len),这两种情况不会发生覆盖,因此可以按正常方式拷贝。 我们编写测试函数,使用assert来验证返回值以及拷贝的内容是否正确。 另外,由于函数使用了`unsigned long`,其长度在不同平台可能不同,为了可移植性,我们使用`sizeof(unsigned long)`来获取步长。在测试时,我们需要注意步长的影响。 由于函数返回的是拷贝的字节数(正常时返回len,错误时返回-1),所以我们可以通过返回值判断是否成功。同时,我们需要验证目标内存的内容是否正确。 编写测试函数`test_bulk_mem_copy`,并在main函数中调用测试函数,同时提供交互模式(例如,根据用户输入选择测试或手动输入参数进行测试)。 步骤: 1. 完成函数,在最后返回len。 2. 编写测试函数,使用多个测试用例。 3. 编写main函数,提供两种模式:自动测试和手动测试。 注意:手动测试时,需要用户输入源字符串、目标地址(实际上我们可以让用户输入一个字符串,然后自己分配内存)和长度,然后调用函数并打印结果。 但是,手动测试输入内存地址比较困难,我们可以让用户输入一个字符串,然后指定拷贝的偏移量(模拟重叠情况)。例如,用户输入一个字符串,然后我们将其复制到一个足够大的缓冲区,并指定目标地址在缓冲区中的位置,从而模拟重叠。 由于手动测试比较复杂,我们可以设计简单的交互:输入源字符串,然后输入目标位置的偏移量(相对于源缓冲区的偏移),然后输入拷贝长度。然后我们分配内存,并设置源缓冲区和目标缓冲区(目标缓冲区位置为源缓冲区地址+偏移量),然后调用函数,并打印结果。 但是,考虑到时间和复杂性,我们按照要求先进行assert测试,然后提供一个简单的交互。 我们首先完成函数和测试代码。</think>### 解决方案 以下是完整的 `bulk_mem_copy` 函数实现,包含返回值、测试函数和交互式 `main` 函数。函数在成功时返回拷贝的字节数,失败时返回 `-1`。 ```c #include <stdio.h> #include <string.h> #include <assert.h> int bulk_mem_copy(unsigned char *to, const unsigned char *from, int len) { if (to == NULL || from == NULL || len <= 0) { printf("操作不合法!\n"); return -1; } /* 地址交叠检测 */ if ((from < to) && (to < from + len)) { /* 从后向前拷贝避免覆盖 */ to += len - 1; from += len - 1; while (len--) { *to-- = *from--; } } else { /* 无覆盖时按机器字长批量拷贝 */ size_t step_length = sizeof(unsigned long); int cnt_cpy = len / step_length; int byte_remain = len % step_length; unsigned long *dst_step = (unsigned long *)to; const unsigned long *src_step = (const unsigned long *)from; for (int cnt_opt = 0; cnt_opt < cnt_cpy; ++cnt_opt) { *dst_step++ = *src_step++; } /* 拷贝剩余字节 */ unsigned char *dst_byte = (unsigned char *)dst_step; const unsigned char *src_byte = (const unsigned char *)src_step; for (int cnt_restbit = 0; cnt_restbit < byte_remain; cnt_restbit++) { *dst_byte++ = *src_byte++; } } return len; // 成功时返回拷贝的字节数 } // 测试函数 void test_bulk_mem_copy() { // 测试用例1:正常拷贝(不重叠) char src1[] = "HelloWorld"; char dst1[20] = {0}; assert(bulk_mem_copy((unsigned char*)dst1, (unsigned char*)src1, 10) == 10); assert(strcmp(dst1, "HelloWorld") == 0); // 测试用例2:地址重叠(向后覆盖) char data2[] = "1234567890"; assert(bulk_mem_copy((unsigned char*)data2+3, (unsigned char*)data2, 7) == 7); assert(strcmp(data2, "1231234560") == 0); // 预期结果 // 测试用例3:地址重叠(向前覆盖) char data3[] = "ABCDEFGHIJ"; assert(bulk_mem_copy((unsigned char*)data3, (unsigned char*)data3+2, 8) == 8); assert(strcmp(data3, "CDEFGHIJIJ") == 0); // 预期结果 // 测试用例4:非法输入 char valid[] = "Test"; assert(bulk_mem_copy(NULL, (unsigned char*)valid, 4) == -1); assert(bulk_mem_copy((unsigned char*)valid, NULL, 4) == -1); assert(bulk_mem_copy((unsigned char*)valid, (unsigned char*)valid, -1) == -1); // 测试用例5:拷贝空数据(边界值) char dst5[10] = {0}; assert(bulk_mem_copy((unsigned char*)dst5, (unsigned char*)"", 0) == -1); printf("所有测试通过!\n"); } int main() { int mode; printf("选择模式:\n1. 运行测试\n2. 手动测试\n> "); scanf("%d", &mode); getchar(); // 消耗换行符 if (mode == 1) { test_bulk_mem_copy(); } else if (mode == 2) { char src[256], dst[512]; int offset, len; printf("输入源字符串: "); fgets(src, sizeof(src), stdin); src[strcspn(src, "\n")] = '\0'; // 移除换行符 printf("输入目标偏移量: "); scanf("%d", &offset); printf("输入拷贝长度: "); scanf("%d", &len); // 设置目标缓冲区(留出偏移空间) memset(dst, 0, sizeof(dst)); unsigned char *target = (unsigned char*)dst + offset; int result = bulk_mem_copy(target, (unsigned char*)src, len); printf("\n拷贝结果: %s\n", result == -1 ? "失败" : "成功"); printf("返回值: %d\n", result); printf("目标缓冲区内容: ["); for (int i = 0; i < len + 10; i++) { // 打印部分内容 if (dst[i] == 0) printf("\\0"); else printf("%c", dst[i]); } printf("]\n"); } else { printf("无效选择\n"); } return 0; } ``` ### 代码解释 1. **函数实现**- **参数校验**:检查空指针或非法长度,返回 `-1` - **重叠处理**:当 `to` 在 `from` 和 `from+len` 之间时,从后向前拷贝 - **批量拷贝**- 使用 `unsigned long` 进行字长拷贝(通常 4/8 字节) - 计算完整字长块数量 `cnt_cpy` 和剩余字节 `byte_remain` - 通过类型转换批量拷贝字长数据 - 逐字节拷贝剩余数据 - **返回值**:成功时返回拷贝的字节数 `len` 2. **测试函数**- **正常拷贝**:验证字符串完整复制 - **向后覆盖**:测试 `1234567890` → `1231234560` - **向前覆盖**:测试 `ABCDEFGHIJ` → `CDEFGHIJIJ` - **非法输入**:空指针/负长度检测 - **边界值**:零长度拷贝检测 3. **交互模式**- **测试模式**:自动运行所有测试用例 - **手动模式**- 输入源字符串、目标偏移量和拷贝长度 - 显示拷贝结果和目标缓冲区内容 - 特殊字符(如 `\0`)会被转义显示 ### 测试用例说明 1. **向后覆盖**: `src = "1234567890"`, `to = src+3`, `len=7` 结果:`"1231234560"`(`456` 被 `123` 覆盖) 2. **向前覆盖**: `src = "ABCDEFGHIJ"`, `to = src`, `from = src+2`, `len=8` 结果:`"CDEFGHIJIJ"`(`AB` 被 `CDEFGHIJ` 覆盖) 3. **非法输入**: 空指针或负长度触发错误返回 `-1` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值