class test
{
char *str;
public:
test(char *p_str) /**default constructor**/
{
cout<<"Default\n";
int l = strlen(p_str) + 1;
str = (l ? new char[l] : 0);
memcpy(str,p_str,l);
}
test(const test& ob) /**copy**/
{
cout<<"Copy\n";
int l = strlen(ob.str) + 1;
str = (l ? new char[l] : 0);
memcpy(str,ob.str,l);
}
test(test&& ob) /**move constructor **/
{
cout<<"Move Constructor\n";
str = ob.str;
ob.str = nullptr;
}
void my_swap(test &ob1 , test &ob2) /**swap function**/
{
swap(ob1.str , ob2.str);
}
test& operator=(test ob) /**copy is called because of pass by value **/
{
cout<<"Copy Assignment operator\n";
my_swap(*this,ob);
return *this;
/**copy is destroyed as object passed by value is destroyed just after the function returns;**/
}
~test()
{
cout<<"Destructor\n";
delete[] str;
}
void print_str()
{
cout<<str<<"\n";
}
};
上面的类包含了c ++中5规则的简单实现。现在,当这个类的向量被创建如下时。
int main()
{
vector<test> vec1;
vec1.push_back(test("Hi!There"));
return 0;
}
我得到以下输出
默认
移动构造函数
析构函数
析构
当另外一个物体像这样被推入矢量时
int main()
{
vector<test> vec1;
vec1.push_back(test("Hi!There"));
vec1.push_back(test("Hello! There"));
return 0;
}
输出
默认
移动构造函数
析构函数
默认
移动构造函数
复制
析构函数
析构函数
析构函数
析构
现在我的问题是为什么在第二种情况下调用复制构造函数而不是第一种情况。
Thanku
答案 0 :(得分:1)
由于您有5个析构函数调用而不是4个,我假设当您尝试推送第二个项目时,向量必须重新分配它的内部存储。这意味着向量必须将第一个推送项移动到新分配的(更大)内存区域。但是,当向量重新分配存储并且必须从旧存储器块传输新项目时,可能会发生该项目是通过复制而不是移动来传输的。原因:How to enforce move semantics when a vector grows?
在您的情况下,正确的解决方案是使用vec1.reserve(2)
(在推送项目之前)以避免不必要的重新分配,即使重新分配与移动一起发生。频繁的重新分配通常是内存使用优化的目标。