这可能是个愚蠢的问题。
假设我们在C++11域,我们使用make_shared()创建一个智能指针。然后,我们使用这个智能指针初始化一个变量,如下所示:
std::shared_ptr<class> = make_shared(/* args to c'tor of class*/ );现在我知道两件事:
make_shared.shared_ptr调用副本构造函数,这在C++17.中是强制性的。
这是否意味着在make_shared的每个实例中都会创建shared_ptr的临时副本并将其插入副本构造函数中?因为这意味着线程安全,如果其他线程抢占线程并调用shared_ptr::use_count()成员函数,则必须在初始化过程中执行锁。
发布于 2022-03-19 15:00:20
有两件事可以避免复制:
optimization);
是
对于代码auto foo = std::make_shared<Foo>();,RVO将直接在堆栈上创建对象。即使我们通过-fno-elide-constructors禁用RVO,移动构造函数也会尝试使用,因为从make_shared返回的对象是临时的。
下面是一个简单的测试代码。(这段代码只显示了概念,而不是真实世界的shared_ptr实现)
#include <iostream>
template <typename T>
struct my_shared_ptr
{
T *t_{nullptr};
my_shared_ptr(T *t): t_(t) {
std::cout << "constructor" << std::endl;
};
my_shared_ptr(const my_shared_ptr<T>&) {
std::cout << "copy" << std::endl;
}
my_shared_ptr<T>& operator=(const my_shared_ptr<T>&) {
std::cout << "copy" << std::endl;
return *this;
}
#ifndef NO_MOVE
my_shared_ptr(my_shared_ptr<T>&&) {
std::cout << "move" << std::endl;
}
my_shared_ptr<T>& operator=(my_shared_ptr<T>&&) {
std::cout << "move" << std::endl;
return *this;
}
#endif
};
template <typename T>
my_shared_ptr<T>
my_make_shared() {
return my_shared_ptr<T>(new T);
}
struct Foo {};
int main()
{
auto foo = my_make_shared<Foo>();
return 0;
}使用c++11编译的条件1显示:
$ g++ a.cc -std=c++11 ; ./a.out
constructor使用c++11/禁用RVO编译的条件2显示:
$ g++ a.cc -std=c++11 -fno-elide-constructors ; ./a.out
constructor
move
move条件3,使用c++11/禁用RVO/no move编译显示:
$ g++ a.cc -std=c++11 -fno-elide-constructors -DNO_MOVE ; ./a.out
constructor
copy
copyhttps://stackoverflow.com/questions/71536672
复制相似问题