使用已使用 new X() 创建的变量将 std::unique_ptr 传递给函数
Passing std::unique_ptr to a function by using a variable that is already created using new X()
我是 C++ 的新手,对以下两种情况下发生的情况有些困惑。
- 我使用 new 关键字创建变量,然后将该变量作为 std::unique_ptr<>(x) 传递给函数。当我这样做时,我仍然可以从我传递的 class 访问 this->handler_。
注意:Y 是 X
的超 class
this->handler_ = new X(this);
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>( this->handler_));
- 将变量创建为唯一指针并直接传递。
注意:Y 是 X
的超 class
this->handler_ = std::unique_ptr<Y>(new X(this));
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>( std::move(handler_)));
对于第二种情况,我知道 std::move()
移动对象并将所有权转移给我们传递的函数。但是在第一种情况下实际发生了什么?如果有人能清楚地解释,我将不胜感激,因为我不是很精通 C++。谢谢
在第一种情况下,创建了一个 unique_ptr 实例,分配的内存开始由其生命周期管理,即发生隐式所有权转移。
在第一种情况下,您正在使用原始指针构建 std::unique_ptr
。
在这种情况下,您通过构造 unique_ptr 将指针的所有权转移给 unique_ptr 。 RAII 表示 Resource Aquisition Is I初始化。您使用要拥有的指针初始化唯一指针,该唯一指针负责清理它。
调用函数后,this->handler_
是一个指向可能被销毁对象的非空指针。
我建议总是使用第二种情况,或者更好(如果你有 C++14):
this->handler_ = std::make_unique<X>(this);
auto res1 = root()->grpcStreamHandler(std::move(this->handler_));
make unique 函数将负责更新对象。
在第一种情况下,this->handler_
是一个指针,unique_ptr
拥有 this->handler_
指向的对象的所有权。
在以常规方式销毁该对象之前,旧指针一直有效。
不允许将指针传递给 delete
,除非对象的所有者 release
是它。
在第二种情况下,this->handler_
表示具有唯一但可转让所有权的对象。
通过将其转移给新所有者来转移所有权后,原所有者一无所有。
在第一种情况下,this->handler_
最终包含一个它不拥有的指针(unique_ptr
拥有它,并且 delete
当 unique_ptr
除非手动从 unique_ptr
中提取,否则会被销毁)。如果有任何尝试 delete this->handler_
(例如析构函数通常会在合理的 类 上使用指针成员做什么)你正在双重释放内存(未定义的行为),或者如果他们试图在 unique_ptr
清理它,您正在访问释放的内存(也未定义)。
基本上,选项 #1 几乎肯定是错误的,即使它没有错,它也是最糟糕的代码味道(你分配并存储为实例属性的指针,而不 delete
? 不寒而栗 )。您想要选项 #2,或者更准确地说,它的更简单版本:
auto res1 = root()->grpcStreamHandler(std::move(handler_));
这避免了显式构造传递给该方法的新 unique_ptr
,而无论如何它都是移动构造的。实际上,如果您所做的只是立即摆脱它,您可能根本 不想要 this->handler_
,只需:
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>(new X(this)));
和construct/pass它是一个单一的动作(可以省略移动)。
我是 C++ 的新手,对以下两种情况下发生的情况有些困惑。
- 我使用 new 关键字创建变量,然后将该变量作为 std::unique_ptr<>(x) 传递给函数。当我这样做时,我仍然可以从我传递的 class 访问 this->handler_。
注意:Y 是 X
的超 class
this->handler_ = new X(this);
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>( this->handler_));
- 将变量创建为唯一指针并直接传递。
注意:Y 是 X
的超 classthis->handler_ = std::unique_ptr<Y>(new X(this));
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>( std::move(handler_)));
对于第二种情况,我知道 std::move()
移动对象并将所有权转移给我们传递的函数。但是在第一种情况下实际发生了什么?如果有人能清楚地解释,我将不胜感激,因为我不是很精通 C++。谢谢
在第一种情况下,创建了一个 unique_ptr 实例,分配的内存开始由其生命周期管理,即发生隐式所有权转移。
在第一种情况下,您正在使用原始指针构建 std::unique_ptr
。
在这种情况下,您通过构造 unique_ptr 将指针的所有权转移给 unique_ptr 。 RAII 表示 Resource Aquisition Is I初始化。您使用要拥有的指针初始化唯一指针,该唯一指针负责清理它。
调用函数后,this->handler_
是一个指向可能被销毁对象的非空指针。
我建议总是使用第二种情况,或者更好(如果你有 C++14):
this->handler_ = std::make_unique<X>(this);
auto res1 = root()->grpcStreamHandler(std::move(this->handler_));
make unique 函数将负责更新对象。
在第一种情况下,this->handler_
是一个指针,unique_ptr
拥有 this->handler_
指向的对象的所有权。
在以常规方式销毁该对象之前,旧指针一直有效。
不允许将指针传递给 delete
,除非对象的所有者 release
是它。
在第二种情况下,this->handler_
表示具有唯一但可转让所有权的对象。
通过将其转移给新所有者来转移所有权后,原所有者一无所有。
在第一种情况下,this->handler_
最终包含一个它不拥有的指针(unique_ptr
拥有它,并且 delete
当 unique_ptr
除非手动从 unique_ptr
中提取,否则会被销毁)。如果有任何尝试 delete this->handler_
(例如析构函数通常会在合理的 类 上使用指针成员做什么)你正在双重释放内存(未定义的行为),或者如果他们试图在 unique_ptr
清理它,您正在访问释放的内存(也未定义)。
基本上,选项 #1 几乎肯定是错误的,即使它没有错,它也是最糟糕的代码味道(你分配并存储为实例属性的指针,而不 delete
? 不寒而栗 )。您想要选项 #2,或者更准确地说,它的更简单版本:
auto res1 = root()->grpcStreamHandler(std::move(handler_));
这避免了显式构造传递给该方法的新 unique_ptr
,而无论如何它都是移动构造的。实际上,如果您所做的只是立即摆脱它,您可能根本 不想要 this->handler_
,只需:
auto res1 = root()->grpcStreamHandler(std::unique_ptr<Y>(new X(this)));
和construct/pass它是一个单一的动作(可以省略移动)。