【问题标题】:Is this[0] safe in C++?this[0] 在 C++ 中安全吗?
【发布时间】:2013-05-20 17:53:46
【问题描述】:

This earlier question 询问this[0] 在 C# 中的含义。在 C++ 中,this[0] 表示“this 指向的数组的第零个元素。”

是否保证不会导致 C++ 中的未定义行为以这种方式引用接收者对象?我不提倡使用这种语法,我很好奇规范是否保证这将永远有效。

谢谢!

【问题讨论】:

  • 我很确定它的定义很明确,就像&obj + 1 一样。
  • 我有时将它与 gdb 一起使用:假设您使用了p complex-expression-that-yields-pointer,但您想查看对象的内容,而不是指针,所以按下,输入 [0] 并完成。无需滚动到表达式的开头并添加括号(可能)。

标签: c++ arrays pointers language-lawyer this-pointer


【解决方案1】:

对于任何有效的对象指针pp[0] 等价于*p。所以this[0] 等价于*this。没有什么了。就像您可以使用[0] 取消引用任何有效指针一样,您也可以使用它取消引用this

换句话说,写*this只是一种“棘手”的方式。它可以用来混淆代码。它可能也可以在某些特定情况下用于有用的目的,因为任何独立对象都可以被认为是大小为 1 的数组。(来自 C++03,加法运算符:“对于这些运算符,指针指向非数组对象的行为与指向长度为 1 的数组的第一个元素的指针相同,该数组的类型作为其元素类型。")

附:正如 Johannes 在 cmets 中指出的那样,通过使用 C++11 特性,可以提出一个上下文,其中this 是一个指向不完整类型的指针。在这种情况下,this[0] 表达式无效,而*this 表达式仍然有效。

【讨论】:

  • 我很确定您已经意识到这一点,但答案却有所不同。以下是格式错误的,将this[0] 替换为*this 使其格式正确。 struct A { auto f () -> decltype (this [0]); };.
  • 对,正如 Johannes 所说,当 p 是指向不完整类型的指针时,p[0] 不起作用。除此之外,类型可能不完整,因为它尚未完成,如 Johannes 的示例中那样,但也可能是因为类型无法完成(例如 T(*)[])。它(当然)也不适用于非对象指针类型。
【解决方案2】:

this[0]*(this + 0) 相同,所以这确实很好(虽然有点奇怪)。

【讨论】:

  • 对不起,我很迂腐,但是 ISO 规范能保证这一点吗?我很清楚这种身份,但规范经常区分对象和数组。
  • @templatetypedef, &obj + 1 是有效的,不管obj 是一个数组还是单个对象。我会假设这里同样适用。
  • @templatetypedef:实际上,[] 不对数组进行操作,仅对指针进行操作。数组衰减为一个指针,[] 与指针和索引一起工作。所以,是的,这是有保证的。
  • @templatetypedef:来自 C++03,加法运算符:“对于这些运算符,指向非数组对象的指针与指向长度为 1 的数组的第一个元素的指针的行为相同将对象的类型作为其元素类型。”
【解决方案3】:

是的,和*this是一回事

【讨论】:

    【解决方案4】:

    AFAIK 基本上this[0]*this 完全相同,因为this 只是一个普通指针。 所以是的,它可以安全使用。

    array[1]*(array + 1) 相同(当array 有效时)仅供参考...

    【讨论】:

      【解决方案5】:

      它等同于(根据定义)*(this + 0),与*this 相同。它是安全且定义明确的,但很奇怪。

      【讨论】:

        【解决方案6】:

        this[0]*(this + sizeof(this)*0) 一样,所以很安全

        添加了小测试作为评论的答案

        struct A
        {
            void * _a;
            int _b;
        
            A * getThis(int index)
            {
                return &(this[index]);
            }
        };
        
        int main(int argc, char * argv[])
        {
            A mas[100];
        
            std::cout << ((long long) mas[0].getThis(50) == (long long) &(mas[50])) << std::endl;
            return 0;
        }
        

        【讨论】:

        • 虽然您的回答技术上是正确的。 sizeof(this) 是多余的,暗示this[1]*(this + sizeof(this)*1) 相同。或者说this[N] 通常等同于*(this + sizeof(this)*N)。这当然是错误的。
        • @BenjaminLindley 看到小测试,我认为,证明我的观点
        • 我不知道你想用你的测试证明什么。你明白我的评论吗?我的观点是this[N]等同于*(this + sizeof(this)*N),但在我看来,您的原始答案暗示它们是等价的。 sizeof(this) 完全没有意义,只是因为它被乘以 0 而发生了。但对于 N 除了 0 之外的任何其他值,它都不起作用。那么为什么它会出现在你的公式中呢?
        • 指针+整数加法已经被指向对象的大小缩放。 this[0] 恰好与*(this + sizeof(this)*0) 相同,但this[N] *(this + sizeof(this) * N)'相同;相反,它等价于*(this + N)(即对象N * sizeof *this 字节,或更简单的N 元素,经过this 指向的位置)。无论如何,sizeof(this) 是无关紧要的;这给了你指针的大小,而不是指向对象的大小。
        猜你喜欢
        • 2017-08-16
        • 1970-01-01
        • 2013-06-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-07
        • 2021-01-10
        • 1970-01-01
        相关资源
        最近更新 更多