Soh*_*hof 4 c++ syntax expression declaration shared-ptr
我试图了解 ashared_ptr p在构造未命名时的用法shared_ptr以及它对 的影响p。我正在研究自己的示例并编写了以下代码:
shared_ptr<int> p(new int(42));
cout << p.use_count() << '\n';
{
cout << p.use_count() << '\n';
shared_ptr<int>(p);
cout << p.use_count() << '\n';
}
cout << p.use_count() << '\n';
Output:
1
1
0
1
Run Code Online (Sandbox Code Playgroud)
p第 5 行用于创建临时变量是否正确。shared_ptr(即未命名的shared_ptr)?use_count增加。在我们退出第 7 行的块之前,temp.object 是否已被销毁。p块内的使用计数变为零,为什么退出块后它又变成1了?shared_ptr q如果我在第 5 行使用命名,即:
shared_ptr<int>q(p);
Run Code Online (Sandbox Code Playgroud)
一切都会按预期工作,在第 5 行之后的块内,使用计数将为 2,在我们退出该块后,它将再次为 1。
根据 C++ 标准(8.5.1.3 显式类型转换(函数表示法))
1 简单类型说明符 (10.1.7.2) 或类型名称说明符 (17.7) 后跟带括号的可选表达式列表或大括号初始化列表(初始化程序),在给定初始化程序的情况下构造指定类型的值...
所以这个表达式语句中的表达式
shared_ptr<int>(p);
Run Code Online (Sandbox Code Playgroud)
看起来像一个显式类型转换(函数)表达式。
另一方面,声明中的声明符可以用括号括起来。例如
int ( x );
Run Code Online (Sandbox Code Playgroud)
是一个有效的声明。
所以这个声明
shared_ptr<int>(p);
Run Code Online (Sandbox Code Playgroud)
可以被解释为像这样的声明
shared_ptr<int> ( p );
Run Code Online (Sandbox Code Playgroud)
所以存在一个歧义。
C++ 标准通过以下方式解决了这种歧义(9.8 歧义解决)
1 涉及表达式语句和声明的语法存在歧义:以函数样式显式类型转换 (8.5.1.3) 作为其最左侧子表达式的表达式语句与第一个声明符以 ( 开头的声明无法区分。在这些情况下,声明就是声明。
因此内部代码块中的这条语句
shared_ptr<int>(p);
Run Code Online (Sandbox Code Playgroud)
是一个新共享指针的声明,其名称p隐藏了外部代码块中同名对象的先前声明p,并且是使用默认构造函数创建的
constexpr shared_ptr() noexcept;
Run Code Online (Sandbox Code Playgroud)
根据这个构造函数的描述
2 作用:构造一个空的shared_ptr对象。
3 后置条件:use_count() == 0 && get() == nullptr。
如果您想处理表达式而不是声明,那么您所需要做的就是将语句主体括在括号中,从而在表达式语句中获取主表达式。
这是一个演示程序。
#include <iostream>
#include <memory>
int main()
{
std::shared_ptr<int> p( new int( 42 ) );
std::cout << "#1: " << p.use_count() << '\n';
{
std::cout << "#2: " << p.use_count() << '\n';
( std::shared_ptr<int>( p ) );
std::cout << "#3: " << p.use_count() << '\n';
}
std::cout << "#4: " << p.use_count() << '\n';
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,它的输出是
#1: 1
#2: 1
#3: 1
#4: 1
Run Code Online (Sandbox Code Playgroud)