【发布时间】:2021-12-22 10:46:44
【问题描述】:
考虑这段代码:
#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;
struct BigInteger
{
vector<int> arr;
BigInteger()
{
cout << "default constructor" << endl;
this->arr.push_back(0);
}
BigInteger(initializer_list<int> il)
{
cout << "initializer_list constructor" << endl;
for (const int x : il)
{
arr.push_back(x);
}
}
BigInteger(const BigInteger& obj) //copy constructor
{
cout << "copy constructor" << endl;
this->arr = obj.arr;
}
BigInteger(BigInteger&& obj) //move constructor
{
cout << "move constructor" << endl;
swap(*this, obj);
}
~BigInteger() //destructor
{
cout << "destructor" << endl;
arr.clear(); //probably because of RAII, I guess I don't have to write this
}
BigInteger& operator=(const BigInteger& rhs)
{
cout << "copy assignment" << endl;
BigInteger tmp(rhs);
this->arr = tmp.arr;
return *this;
}
BigInteger& operator=(BigInteger&& rhs) noexcept
{
cout << "move assignment" << endl;
swap(*this, rhs);
return *this;
}
};
int main()
{
BigInteger another = BigInteger({0, 1, 2});
}
所以,我正在创建一个临时对象BigInteger({0, 1, 2}),然后为我的类实例a(理论上)进行移动分配。所以预期的输出是:
initializer_list 构造函数 //创建临时对象
默认构造函数//创建glvalue(非临时)对象
移动作业
析构函数
但是输出是:
initializer_list 构造函数
析构函数
我什至不明白为什么会这样。我怀疑operator=和初始化不一样,但还是不明白我的对象是怎么构造的。
【问题讨论】:
-
你说得对,赋值与初始化是分开的。语法中的
=是红鲱鱼。 -
@Frank 所以复制省略有点直接初始化我的数据成员?我可以以某种方式明确禁止复制省略吗?
-
@Learpcs 自 C++17 起,
BigInteger another = BigInteger({0, 1, 2});被编译为好像它被写为BigInteger another({0, 1, 2});,所以没有临时的BigInteger对象可以优化掉。你不能禁止它,你只能解决它,例如先将BigInteger({0, 1, 2})保存到另一个变量,或者将它移动到一个函数中,然后从该函数的返回中初始化another。但即便如此,复制省略仍将尝试优化 tempBigInteger对象。您不能禁用复制省略,但在某些情况下有办法使其不可行。
标签: c++ oop move-semantics move-constructor copy-elision