我曾经假设类的移动构造函数将优先于其复制构造函数,但在下面的代码中,即使对象应该是可移动的,似乎也会选择复制构造函数。
你知道为什么下面的代码选择复制构造函数吗foo()
回报vector<B> B
?
#include <iostream>
#include <vector>
using namespace std;
class B {
public:
int var_;
B(int var) : var_(var)
{
cout << "I'm normal" << endl;
}
B(const B& other)
{
cout << "I'm copy constructor" << endl;
}
B(B&& other)
{
cout << "I'm move constructor" << endl;
}
};
vector<B> foo()
{
vector<B> b;
b.push_back(1);
b.push_back(2);
return b;
}
int main()
{
vector<B> b {foo()};
}
结果如下图所示。
$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor
I'm normal
I'm move constructor
I'm copy constructor
奇怪的是,如果我删除一行foo()
,改为选择移动构造函数:
vector<B> foo()
{
vector<B> b;
b.push_back(1);
return b;
}
现在结果如下:
$ g++ main.cpp
$ a.out
I'm normal
I'm move constructor
这涉及到两件事:向量重新分配和重新分配时机制的选择。
首先,重新分配发生在这里:
vector<B> foo()
{
vector<B> b;
b.push_back(1);
std::cout << "Vector capacity: " << b.capacity() << " Vector size: " << b.size() << "\n";
b.push_back(2); //capacity() == size(), reallocation is needed
return b;
}
大多数矢量实现都会产生容量2*current_capacity
when current_capacity
将被超出,以符合标准要求的摊余常数复杂性。
现在,如果标记为,编译器只能选择移动构造函数进行重新分配noexcept
。为了使向量使用移动构造函数,请像这样声明:
B(B&& other) noexcept
{
//
}
您可以通过预先保留空间来完全删除重新分配:
vector<B> foo()
{
vector<B> b;
b.reserve(2);
b.push_back(1);
b.push_back(2);
return b;
}
或者通过一次性初始化向量:
vector<B> foo()
{
return vector<B>{1, 2};
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)