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>());

只是为了澄清,因为我今天也有同样的情况,但我很难看出差异。