C++ 当 function returns vector<shared_ptr<>> 时会发生什么?
C++ what happens when function returns vector<shared_ptr<>>?
我有以下代码:
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
Test() {}
~Test() { std::cerr << "Delete\n"; }
};
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
list.push_back(std::make_shared<Test>(Test()));
return std::move(list);
}
int main(int argc ,char **argv)
{
std::vector<std::shared_ptr<Test>> list;
std::cerr << "Before\n";
list = makeList();
std::cerr << "After\n";
return 0;
}
我用它编译:
clang++ -std=c++14 -o ptr ptr.cpp
输出为:
Before
Delete
After
Delete
我的问题是:为什么在makeList
函数中有一个对象被删除了?我的假设是函数中的 list
将从 main
移动到 list
,因此在此过程中没有对象 deleted/recreated?
可以避免这种情况吗(显然这段代码不是最佳的)?
list.push_back(std::make_shared<Test>(Test()));
此处使用 Test()
创建了临时文件。然后调用 copy c-tor for Test
并销毁临时文件。这是第一个析构函数调用。
当list
被销毁时,第二次析构函数调用出现在程序末尾。
避免临时创建的正确形式是:
list.push_back(std::make_shared<Test>());
此外,您不应该使用 std::move
返回值,因为在这种情况下编译器无法应用 Return 值优化。
行list.push_back(std::make_shared<Test>(Test()));
创建一个临时Test
,然后将其移动到std::make_shared<T>
构造的实际Test
中。然后销毁这个临时文件。
std::make_shared<T>
要求参数用于构造 T
。对于默认构造的 T
,只需不提供任何参数。
在这种情况下,正确的用法是这样的:
list.push_back(std::make_shared<Test>());
2 项更改:
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
// make_shared does not need a copy of an object, just constructor arguments
list.push_back(std::make_shared<Test>());
// return std::move(list) will defeat RVO. Never do that.
return list;
}
所以,重要的部分是:
list.push_back(std::make_shared<Test>(Test()));
->
list.push_back(std::make_shared<Test>());
只是为了澄清,因为我今天也有同样的情况,但我很难看出差异。
我有以下代码:
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
Test() {}
~Test() { std::cerr << "Delete\n"; }
};
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
list.push_back(std::make_shared<Test>(Test()));
return std::move(list);
}
int main(int argc ,char **argv)
{
std::vector<std::shared_ptr<Test>> list;
std::cerr << "Before\n";
list = makeList();
std::cerr << "After\n";
return 0;
}
我用它编译:
clang++ -std=c++14 -o ptr ptr.cpp
输出为:
Before
Delete
After
Delete
我的问题是:为什么在makeList
函数中有一个对象被删除了?我的假设是函数中的 list
将从 main
移动到 list
,因此在此过程中没有对象 deleted/recreated?
可以避免这种情况吗(显然这段代码不是最佳的)?
list.push_back(std::make_shared<Test>(Test()));
此处使用 Test()
创建了临时文件。然后调用 copy c-tor for Test
并销毁临时文件。这是第一个析构函数调用。
当list
被销毁时,第二次析构函数调用出现在程序末尾。
避免临时创建的正确形式是:
list.push_back(std::make_shared<Test>());
此外,您不应该使用 std::move
返回值,因为在这种情况下编译器无法应用 Return 值优化。
行list.push_back(std::make_shared<Test>(Test()));
创建一个临时Test
,然后将其移动到std::make_shared<T>
构造的实际Test
中。然后销毁这个临时文件。
std::make_shared<T>
要求参数用于构造 T
。对于默认构造的 T
,只需不提供任何参数。
在这种情况下,正确的用法是这样的:
list.push_back(std::make_shared<Test>());
2 项更改:
std::vector<std::shared_ptr<Test>> makeList()
{
std::vector<std::shared_ptr<Test>> list;
// make_shared does not need a copy of an object, just constructor arguments
list.push_back(std::make_shared<Test>());
// return std::move(list) will defeat RVO. Never do that.
return list;
}
所以,重要的部分是:
list.push_back(std::make_shared<Test>(Test()));
->
list.push_back(std::make_shared<Test>());
只是为了澄清,因为我今天也有同样的情况,但我很难看出差异。