当前位置: 首页 > 知识库问答 >
问题:

将[[no_unique_address]]应用于函数体内的范围守卫

龙涵蓄
2023-03-14

我想使用无状态作用域防护

struct ScopeGuard {
    ScopeGuard();
    ~ScopeGuard();
};

void f();

int test() {
    ScopeGuard scopeguard1;
    ScopeGuard scopeguard2;
    // doesn't work:
    // [[no_unique_address]] ScopeGuard scopeguard3;
    f();
}

范围保护本身没有状态,我只对构造函数/析构函数的副作用感兴趣。

我希望test的堆栈大小为0。但是scope eGuard d1scope eGuard d2各占用8个字节的堆栈空间。这是因为this指针对于ScopeGuard的每个实例都需要是唯一的,即使它是无状态的。

通常,我想在这种情况下使用[[no_unique_address]]。但是[[no_unique_address]似乎只适用于成员变量,而不适用于函数内部的局部变量。

有没有其他方法来实现这一点?为什么[[no_unique_address]]只支持成员变量?这是C20的疏忽吗?这是故意的吗?允许局部变量也使用此属性会有什么问题吗?

共有1个答案

幸乐湛
2023-03-14

我希望test的堆栈大小为0。但是scope eGuard d1scope eGuard d2各占用8个字节的堆栈空间。这是因为this指针对于ScopeGuard的每个实例都需要是唯一的,即使它是无状态的。

你怎么知道他们没有?

如果编译器可以看到,ScopeGuard中的任何内容实际上都不关心这个指针的值,并且实际上没有人尝试获取这种类型的堆栈变量的地址,那么编译器可以100%自由地在堆栈上不给这样的变量空间。

此外,您还误解了no_unique_address的部分行为。尽管有名称,但它实际上不允许相同类型的两个实例具有相同的地址。它允许不同类型的两个实例在成员布局中重叠。因此,即使您可以使用该属性声明这些局部变量,编译器也无法为它们提供相同的地址(假设有人查看了地址)。

no_unique_address对于成员变量是必需的,因为 C 对类型的布局方式有特定的规则,并且每个成员都需要自己的存储区域,而该区域与其他所有成员不同。no_unique_address允许成员违反该规则,只要满足唯一标识规则即可。

对于局部变量,编译器可以选择在它认为合适的情况下优化堆栈,因此它不需要no_unique_address来授予它权限。

别忘了:< code>no_unique_address也不提供任何保证。它让编译器可以选择优化掉一些东西;从来不是强制的。

 类似资料:
  • 我对C很陌生,现在就在做中学习。在课堂材料中,我有以下功能: 几分钟前,我像这样使用了普通for循环:

  • 我试过这个: 但这扩展了弦中的基因,这不是我想要的。

  • 对于我的Java类,我正在编写一个小程序,首先选择一个介于1和100之间的数字。然后,它会提示用户开始猜测正确的。如果用户对的猜测过高或过低,程序会打印出一个新范围,供他们在该范围内进行猜测。如果用户输入或,程序只需重新要求用户输入,但不会以任何方式更改范围。 示例输出(当机密号为20时)如下所示: 该项目似乎已经基本完成,但只有一个例外。其中一个要求是,当用户键入的超出我们给定的1和100范围时

  • 本文向大家介绍dart函数范围,包括了dart函数范围的使用技巧和注意事项,需要的朋友参考一下 示例 Dart函数也可以匿名声明或嵌套声明。例如,要创建嵌套功能,只需在现有功能块中打开一个新功能块 该函数innerFunction现在可以在内部使用,并且只能在内部使用outerFunction。没有其他任何功能可以访问它。 Dart中的函数也可以匿名声明,通常用作函数参数。一个常见的例子是对象so

  • 我的方法是生成所有素数直到(埃拉托色尼筛),并检查给定范围内的每个数是否可被素数的平方整除。这些数字的计数从范围的长度中减去,以给出平方自由数。 但是这种方法在复杂度上超时了,请建议一些其他的方法