问题不在赋值而在对 string 的使用:您对 string 的下标访问是越界的。在容器中,有这样两个大小的概念,分别是容量和大小。其中容量是容器当前最多能够容纳的元素个数,而大小是当前已经实际存储的元素个数。您使用下标访问 data 的方式直接对底层进行了访问,这一步骤是没有越界检查的,而由于默认构造的空(大小为 0 ) string 的容量很可能不为 0 ,因此访问此处的内存是合法的,因而当数据较小时出现诡异的结果,而较大时由于越界而直接报错。
因为直接访问了底层,向 string 添加字符的操作未经过容器的正规接口,容器并不知道自己存储了有效的数据,因此第 99 行赋值时调用 string 的赋值操作符时不会复制这些数据,则在容器的视角看来赋值操作实际进行的是“把一个空字符串复制到 c 中的 data ”,显然这会造成无法从 c 中读出正确的结果。而由于尽管您修改容器内部存储空间的操作对容器不可见,但是您从中读取的操作同样是自行进行的,因此对于 a + b 得到的结果直接读取是能够得到正确结果的。
总结起来,您的问题在于对 string 等标准库容器的理解和使用,可能还需要进一步学习。如果不自信,在初学阶段可以考虑不要使用容器的 [] 运算符而是使用 at 方法,这会引入边界检查从而帮助发现一些问题。另外,个人认为在重载 + 操作符时修改操作数的行为(您的代码中补零的操作)是欠妥的,直观上 + 操作符不应该对两个操作数造成任何(外部可见的)修改。(当然您的实现方式实际上对外部不可见,但是这种实现方式是错误的,因此可能还是需要重新考虑补零这一部分。)
感觉自己没说明白,献丑在您的基础上稍作修改了一下,显然并不是最好的写法,您可以视情况参考。
- #include <iostream>
- #include <string>
- #include <algorithm>
- using namespace std;
- class BigInt
- {
- public:
- BigInt();
- void getData();
- void printData()const;
- BigInt operator+(const BigInt &n)const; // 必须传引用,若传值,参数传入函数后会调用构造函数把原本的数据初始化
-
- private:
- string data; // 大数
- static int addWithCarry(int value, int& carry); // 处理带进位加法,减少代码重复
- };
- BigInt::BigInt() = default;
- void BigInt::getData()
- {
- getline(cin, data);
- reverse(data.begin(), data.end()); // 反转字符串
- }
- void BigInt::printData()const
- {
- for(int i = data.size() - 1; i >= 0; --i) cout << data[i];
- cout << '\n';
- }
- BigInt BigInt::operator+(const BigInt &n)const
- {
- BigInt result;
- int carry = 0;
- unsigned int i = 0;
- while(i < data.size() && i < n.data.size()){
- result.data.push_back(addWithCarry(data[i] - '0' + n.data[i] - '0', carry) + '0');
- ++i;
- }
- while(i < data.size()){
- result.data.push_back(addWithCarry(data[i] - '0', carry) + '0');
- ++i;
- }
- while(i < n.data.size()){
- result.data.push_back(addWithCarry(n.data[i] - '0', carry) + '0');
- ++i;
- }
- if(carry != 0) result.data.push_back('1');
- return result;
- }
- int BigInt::addWithCarry(int value, int& carry){
- carry = (value += carry) >= 10 ? 1 : 0;
- return carry ? value - 10 : value;
- }
- int main()
- {
- BigInt a, b, c; // 创建对象
-
- a.getData(); // 输入数据
- b.getData();
- c = a + b;
-
- (a + b).printData();
- c.printData();
-
- return 0;
- }
复制代码
(一开始没想到问题会出在这里,把我给整不自信了,去翻了半天 C++ 标准,还以为记错了默认赋值运算符的行为……)