提问人:cppdev 提问时间:9/14/2023 更新时间:9/14/2023 访问量:120
std::move 和 std::shared_ptr 参数按值传递
std::move and std::shared_ptr argument passed by value
问:
请考虑以下代码:
#include <iostream>
#include <memory>
class Test
{
public:
Test(int t) : t(t) {}
int t;
};
void test(std::shared_ptr<Test> t)
{
std::cout << t.use_count() << std::endl;
}
int main()
{
auto t = std::make_shared<Test>(1);
test(std::move(t)); //(1)
test(std::make_shared<Test>(2)); //(2)
}
问题:
- 在情况 (1) 中执行什么 ctor - 复制或移动?
- 如果 (2) 创建了 time,则执行 copy ctor 以在 中创建,然后销毁 temper。这是对的吗?
t
void test(std::shared_ptr<Test> t)
答:
4赞
Ted Lyngmo
9/14/2023
#1
您的示例中总共创建了 3 个:std::shared_ptr<Test>
auto t = std::make_shared<Test>(1);
test(std::move(t));
- 接收输入是移动构造的。t
test()
test(std::make_shared<Test>(2));
- 接收是由 创建的接收。它是同一个对象,因为自 C++ 17 以来强制复制/移动省略。t
make_shared()
在 C++ 17 之前,理论上你可以得到多达 5 个实例化 - 但由于这种省略在以前的版本中是允许的(但不是强制性的),所以在这些版本中你很可能也只能得到 3 个。使用这些早期版本之一时,您可以在某些编译器(例如/)中使用 关闭此优化。在 C++ 17 及更高版本中,省略是必需的,因此无法关闭。
g++
clang++
-fno-elide-constructors
这是一个演示,它不使用,而是使用一个名为的测试类,以便您可以跟踪每个实例化。请注意,只有一个值为 ,它对应于您的调用。shared_ptr
foo
foo
2
test(std::make_shared<Test>(2));
评论
0赞
cppdev
9/14/2023
您的意思是,如果与例如C++11编译器一起使用,那么在我的示例中,如果(2)将使用移动ctor创建接收?-fno-elide-constructors
t
0赞
Ted Lyngmo
9/14/2023
@cppdev 是的(例如,gcc 有 no-elide-constructors
而 clang 没有),并注意当使用该选项时 () 也会导致移动构造,因此总共有 5 个实例。auto t = std::make_shared<Test>(1);
auto t = make_foo(1);
评论
std::shared_ptr<Test>
Test
Test
t
use_count