提问人:Learpcs 提问时间:11/10/2021 最后编辑:Learpcs 更新时间:11/10/2021 访问量:100
为什么复制构造函数被调用两次?C++
Why is copy constructor called twice? C++
问:
因此,我正在创建一个类 BigInteger,以便更好地理解类中对象的构造方式。因此,请考虑以下代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <initializer_list>
#include <exception>
#include <string>
using namespace std;
struct BigInteger
{
const int base = 1000 * 1000 * 1000; //9 digits.
bool negative = false;
vector<unsigned long long> arr;
BigInteger()
{
#ifdef _DEBUG
cout << "default constructor called" << endl;
#endif // DEBUG
}
BigInteger(const string& s)
{
#ifdef _DEBUG
cout << "string constructor called" << endl;
#endif // DEBUG
/* crutch but seem to work
left - left bound for reading the string to exclude the minus sign.
*/
char left = 0;
if (s[0] == '-')
{
this->negative = true;
++left;
}
for (int i = s.size() - 9; i >= left; i -= 9)
{
#ifdef _DEBUG
if (!(s[i] >= '0' && s[i] <= '9'))
{
throw std::invalid_argument("Error: expected a valid number");
}
#endif // DEBUG
this->arr.push_back(stoll(s.substr(i, 9)));
}
if ((s.size() - left) % 9 != 0)
{
this->arr.push_back(stoll(s.substr(left, (s.size() - left) % 9)));
}
}
friend istream& operator>>(istream& in, BigInteger& obj)
{
#ifdef _DEBUG
cout << "istream& operator>> called: ";
#endif // DEBUG
string s;
in >> s;
obj = BigInteger(s);
return in;
}
friend ostream& operator<<(ostream& out, const BigInteger& obj)
{
if (obj.negative)
out << '-';
out << obj.arr[obj.arr.size() - 1];
string substr;
for (int i = obj.arr.size() - 2; i >= 0; --i)
{
substr = to_string(obj.arr[i]);
for (size_t i = 0; i < 9 - substr.size(); i++)
{
out << '0';
}
out << substr;
}
return out;
}
BigInteger(const BigInteger& obj) //copy constructor
{
#ifdef _DEBUG
cout << "copy constructor called" << endl;
#endif // DEBUG
this->arr = obj.arr;
}
BigInteger(BigInteger&& obj) //move constructor
{
#ifdef _DEBUG
cout << "move constructor called" << endl;
#endif // DEBUG
swap(obj);
}
~BigInteger() //destructor
{
#ifdef _DEBUG
cout << "destructor called" << endl;
#endif // DEBUG
arr.clear(); //probably because of RAII, I guess I don't have to write this
}
void swap(BigInteger& other)
{
std::swap(this->arr, other.arr);
std::swap(this->negative, other.negative);
}
BigInteger& operator=(const BigInteger& rhs)
{
#ifdef _DEBUG
cout << "copy assignment called" << endl;
#endif // DEBUG=
this->arr = rhs.arr;
return *this;
}
BigInteger& operator=(BigInteger&& rhs) noexcept
{
#ifdef _DEBUG
cout << "move assignment called" << endl;
#endif // DEBUG
swap(rhs);
return *this;
}
BigInteger& operator+=(const BigInteger& rhs)
{
#ifdef _DEBUG
cout << "operator+= called" << endl;
#endif // DEBUG
size_t SIZE = max(this->arr.size(), rhs.arr.size()) + 1;
this->arr.resize(SIZE);
for (size_t i = 0; i < SIZE; i++)
{
if (i < rhs.arr.size())
{
this->arr[i] += rhs.arr[i];
}
if (this->arr[i] >= base)
{
this->arr[i] %= base;
++this->arr[i + 1];
}
}
if (this->arr.back() == 0)
this->arr.pop_back();
return *this;
}
BigInteger operator+(BigInteger rhs)
{
return rhs += *this;
}
};
int main()
{
BigInteger a, b;
cin >> a >> b;
cout << a + b << endl;
}
所以我尝试输入任何数字(例如 43 和 12)。所以我想了解当我尝试调用事物时会发生什么。那么我期待什么:a + b
- 创建右侧对象的副本。
- 对此副本执行。
operator+=
- 返回副本
所以我只期望 1 份。但是不知何故,复制构造函数被调用了两次!输出如下:
default constructor called
default constructor called
istream& operator>> called: 43
string constructor called
move assignment called
destructor called
istream& operator>> called: 12
string constructor called
move assignment called
destructor called
//here the moment where a + b start to executing.
copy constructor called
operator+= called
copy constructor called
destructor called
55
destructor called
destructor called
destructor called
为什么叫了两次? 没有调用任何复制构造函数,我仔细检查了。Operator<<
答: 暂无答案
评论
return rhs += *this;
rhs += *this; return rhs;
BigInteger operator+(const BigInteger& rhs) { BigInteger res{tmp}; res += *this; return res; }
可能会触发 NRVO( 是一个局部变量)。 (来自之前的评论)无法触发 NRVO,此举是因为是一个参数。res
return rhs;
rhs