gpt4 book ai didi

c++ - 相同指令的输出不同 - 移动和复制 ctor

转载 作者:行者123 更新时间:2023-11-28 01:19:19 25 4
gpt4 key购买 nike

谁能解释一下这里到底发生了什么,因为我有点困惑。

这是我的代码

{
public:
MetaData (int size, const std::string& name)
: _name( name )
, _size( size )
{
std::cout << "Call of Metadata(int, string) ctor " << std::endl;
}

// copy constructor
MetaData (const MetaData& other)
: _name( other._name )
, _size( other._size )
{
std::cout << "Call of MetaData(const MetaData&) copy ctor" << std::endl;
}

MetaData& operator= (const MetaData& other)
{
std::cout << "Call of MetaData& operator= (const MetaData&) ctor" << std::endl;
_size = other._size;
_name = other._name;

return *this;
}
// move constructor
MetaData (MetaData&& other)
: _name( std::move(other._name) )
, _size( other._size )
{
std::cout << "Call of MetaData (MetaData&&) move ctor" << std::endl;
}

MetaData& operator= (MetaData&& other)
{
_size = other._size;
_name = std::move(other._name);
return *this;
}

std::string getName () const { return _name; }
int getSize () const { return _size; }

private:
std::string _name;
int _size;
};

class ArrayWrapper
{
public:
// default constructor produces a moderately sized array
ArrayWrapper () : _metadata( 64, "ArrayWrapper" )
{
std::cout << "Call of ArrayWrapper() default ctor " << std::endl;
}

ArrayWrapper (int n) : _metadata( n, "ArrayWrapper" )
{
std::cout << "Call of ArrayWrapper(int) default ctor " << std::endl;
}

// move constructor
ArrayWrapper (ArrayWrapper&& other) : _metadata( std::move(other._metadata) )
{
std::cout << "Call of ArrayWrapper (ArrayWrapper&&) move ctor" << std::endl;
}

ArrayWrapper& operator= (ArrayWrapper&& other)
{
std::cout << "Call of ArrayWrapper& operator=(ArrayWrapper&&) assignement ctor" << std::endl;

_metadata = std::move(other._metadata);
return *this;
}


ArrayWrapper& operator= (const ArrayWrapper& other)
{
std::cout << "Call of ArrayWrapper& operator= (const ArrayWrapper&) assignement ctor" << std::endl;
_metadata = other._metadata ;

return *this;
}

// copy constructor
ArrayWrapper (const ArrayWrapper& other) : _metadata( other._metadata )
{
std::cout << "Call of ArrayWrapper (const ArrayWrapper&) copy ctor" << std::endl;
}


~ArrayWrapper ()
{
std::cout << "Delete of ArrayWrapper" <<std::endl;
}
private:
MetaData _metadata;
};

主要是我做了一些测试:

int main()
{
std::vector<ArrayWrapper> v;
v.push_back(ArrayWrapper());
v.push_back(ArrayWrapper());

return 0;
}

第一个 v.push_back(ArrayWrapper()) 输出:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Delete of ArrayWrapper

对我来说,我期望的输出是什么。这让我感到困惑,我期待第二条指令输出完全相同的东西,但这是我得到的:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Call of MetaData(const MetaData&) copy ctor
Call of ArrayWrapper (const ArrayWrapper&) copy ctor
Delete of ArrayWrapper

为什么 ArrayWrapper 的复制构造函数被调用而在第一条指令中却没有被调用?

对我来说,第二个 v.push_back(ArrayWrapper()) 的输出应该是:

Call of Metadata(int, string) ctor
Call of ArrayWrapper() default ctor
Call of MetaData (MetaData&&) move ctor
Call of ArrayWrapper (ArrayWrapper&&) move ctor
Delete of ArrayWrapper //to delete the temporary moved

我哪里错了?

最佳答案

因为vector的容量在第二次调用时发生了变化。这意味着 vector 没有空间容纳更多元素,它会分配新内存(比旧内存大)来存储新项目。在此过程中,它还将现有项目从旧分配内存复制到新内存。这就是为什么您会看到调用了一个额外的 ArrayWrapper 复制构造函数。

int main() {
std::vector<ArrayWrapper> v;
v.push_back(ArrayWrapper());
std::cout << v.capacity() << std::endl;
v.push_back(ArrayWrapper());
std::cout << v.capacity() << std::endl;
return 0;
}

您可以通过移动构造函数 noexcept 来避免该拷贝。

关于c++ - 相同指令的输出不同 - 移动和复制 ctor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57323356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com