gsl::not_null<T*> vs. std::reference_wrapper<T> vs. T&
gsl::not_null<T*> vs. std::reference_wrapper<T> vs. T&
C++ 核心指南最近已经提出(恭喜!(,我担心gsl::not_null
类型。如 I.12 中所述:将不得为 null 的指针声明为 not_null
:
帮助避免取消引用 nullptr 错误。通过以下方式提高性能 避免对 nullptr 进行冗余检查。
。
通过陈述意图 源、实施者和工具可以提供更好的诊断,例如 通过静态分析查找某些类别的错误,并执行 优化,例如删除分支和空测试。
意图很明确。但是,我们已经为此提供了语言功能。不能为 null 的指针称为引用。虽然引用一旦创建就无法重新绑定,但这个问题可以通过std::reference_wrapper
来解决。
我看到gsl::not_null
和std::reference_wrapper
之间的主要区别在于后者只能用于指针而不是指针,而前者适用于nullptr
可分配的任何内容(引用自 F.17:使用not_null表示"null"不是有效值(:
not_null
不仅适用于内置指针。它适用于array_view
、string_view
、unique_ptr
、shared_ptr
等 类似指针的类型。
我想象功能比较表如下所示:
T&
:
- 无法存储
nullptr
? - 是 - 可重新绑定? - 否
- 可以用代替指针以外的东西吗? - 否
std::reference_wrapper<T>
:
- 无法存储
nullptr
? - 是 - 可重新绑定? - 是
- 可以用代替指针以外的东西吗? - 否
gsl::not_null<T*>
:
- 无法存储
nullptr
? - 是 - 可重新绑定? - 是
- 可以代替指针以外的其他东西吗? - 是的
问题:
- 我对这些概念之间差异的理解是否正确?
- 这是否意味着
std::reference_wrapper
现在毫无用处?
PS我为此创建了cpp-core-guidelines
和guideline-support-library
标签,我希望正确。
引用不是不能为空的指针。引用在语义上与指针非常不同。
引用具有值赋值和比较语义;即涉及引用读取和写入引用值的赋值或比较操作。指针具有(违反直觉的(引用赋值和比较语义;也就是说,涉及指针读取和写入引用本身(即引用对象的地址(的赋值或比较操作。
如前所述,引用不能重新绑定(由于其值赋值语义(,但 reference_wrapper<T>
类模板可以重新绑定,因为它具有引用赋值语义。这是因为reference_wrapper<T>
旨在与 STL 容器和算法一起使用,如果其复制赋值运算符不执行与其复制构造函数相同的操作,则其行为将不正确。但是,reference_wrapper<T>
仍然具有值比较语义(如引用(,因此当与 STL 容器和算法一起使用时,它的行为与指针非常不同。例如,set<T*>
可以包含指向具有相同值的不同对象的指针,而set<reference_wrapper<T>>
可以仅包含对具有给定值的一个对象的引用。
not_null<T*>
类模板具有引用赋值和比较语义,类似于指针;它是一种类似指针的类型。这意味着当与 STL 容器和算法一起使用时,它的行为类似于指针。它只是不能为空。
所以,你的评估是对的,除了你忘记了比较语义。不,reference_wrapper<T>
不会被任何类型的指针类型淘汰,因为它具有类似引用的值比较语义。
我认为std::reference_wrapper
仍有gsl::not_null
未涵盖的用例。基本上,std::reference_wrapper
镜像引用并具有operator T&
转换,而not_null
具有与operator->
的指针接口。我立即想到的一个用例是在创建线程时:
void funcWithReference(int& x) { x = 42; }
int i=0;
auto t = std::thread( funcWithReference, std::ref(i) );
如果我无法控制funcWithReference
,我就无法使用not_null
。
这同样适用于算法的函子,我也不得不使用它来绑定boost::signals
。
- 在VS代码中交叉编译Windows与Linux上的MinGW的SDL程序
- 如何为模板化对象创建模板向量?VS正在投掷C3203
- 数据成员SFINAE的C++17测试:gcc vs clang
- 为什么在Windows上的VS 2019和Clang 9中"size_t"在没有标题的情况下工作
- 在for循环中使用auto vs decltype(vec.size())来处理字符串的向量
- 正在VS调试器中监视映射条目
- Confusion: decltype vs std::function
- 将IBM Rhapsody模型集成到VS 2019中
- VS Code "command":"make"与终端窗口中的命令行"make"不同
- 使用VS Code和CMake Tools运行自定义命令
- EASTL矢量<向量<int>>连续的
- 修改 VS Code 中的默认C++代码段
- 如何使用c++在VS 2019上运行SQL查询
- vs 2015 constexpr变量不恒定,但与2019相比还好吗
- 完美前进使用 std::forward vs RefRefCast
- 从VS 2015更新3更新到VS2015更新3 d后浮点计算行为不同的原因
- VS 2015 链接错误 无法构建依赖于 libcurl 的项目
- consteval wrapper vs. source_location
- VS Code C++:不准确的系统包括路径错误(wchar.h,boost/lambda/lambda.hpp)
- QStringList vs list<shared_ptr<QString>> 性能比较C++