这段代码在C++中安全吗?

15

这个早期的问题询问C#中的this[0]是什么意思。在C++中,this[0]表示“指向this所指向的数组的第零个元素”。

在C++中,以这种方式引用接收对象是否保证不会导致未定义的行为?我并不主张使用这种语法,主要是想知道规范是否保证这将始终起作用。

谢谢!


1
我非常确定它是明确定义的,沿着&obj + 1的路线。 - chris
3
有时我会在gdb中使用它:比如你输入了一个复杂的表达式,返回一个指针,但你想要查看对象的内容而不是指针,这时候只需按向上箭头,输入“[0]”,就可以了。无需滚动到表达式开头并添加括号(大概率不需要)。 - rodrigo
6个回答

19
对于任何有效的对象指针pp[0]等价于*p。所以this[0]等同于*this。就像您可以使用[0]解引用任何有效的指针一样,您也可以使用它解引用this
换句话说,这只是一种编写*this的“棘手”方式。它可以用于混淆代码。在某些特定情况下,它可能也可以用于有用的目的,因为任何独立的对象都可以被视为具有长度为1且元素类型为该对象类型的数组。(来自C++03,加性运算符:“对于这些运算符,指向非数组对象的指针与类型为其元素类型的一个长度为1的数组的第一个元素的指针行为相同。”)
附注:正如约翰内斯在评论中指出的那样,通过使用C++11功能,可以构建一个上下文,其中this是指向不完整类型的指针。在这种情况下,this[0]表达式变得无效,而*this表达式仍然有效。

5
我相信你已经意识到了,但是答案表述得有些不同。下面的代码存在问题,将this[0]替换为*this可以解决这个问题。struct A { auto f () -> decltype (this [0]); }; - Johannes Schaub - litb
2
对,Johannes所说的是,当p是指向不完整类型的指针时,p[0]无法使用。此外,类型可能不完整是因为其尚未完成,就像Johannes的例子一样,但也可能是因为无法完成该类型(例如T(*)[])。当然,对于非对象指针类型也无法工作。 - user743382

11

this [0]*(this + 0) 是等价的,因此这样做虽然有点奇怪但是没问题。


2
抱歉我有点苛刻,但是ISO规范保证了这一点吗?我很清楚这个标识,但规范通常会区分对象和数组。 - templatetypedef
@templatetypedef,无论obj是数组还是单个对象,&obj + 1都是有效的。我认为这里也适用。 - chris
3
实际上,[] 操作符不作用于数组本身,而只作用于指针。数组会被转换为指向首元素的指针,[] 操作符会使用该指针和索引值进行操作。因此,是的,这是有保证的。 - rodrigo
5
从C++03版本开始,加法运算符的规定为:“对于这些运算符,指向非数组对象的指针与指向长度为1且元素类型为该对象类型的数组的第一个元素的指针具有相同的行为”。 - AnT stands with Russia

3

没错,它就是*this


1
据我所知,基本上this[0]*this完全相同,因为this只是一个普通指针。所以,使用它是安全的。 array[1]*(array + 1)相同(当array有效时),供您参考...

0

按照定义,它等同于 *(this + 0),这与 *this 相同。它是安全和明确定义的,但很奇怪。


-2

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;
}

7
虽然您的回答从技术上讲是正确的,但 sizeof(this) 是多余的,并暗示着 this[1]*(this + sizeof(this)*1) 相同,或者 this[N] 通常等价于 *(this + sizeof(this)*N)。当然,这是错误的。 - Benjamin Lindley
@BenjaminLindley 看看这个小测试,我认为它证明了我的观点。 - Nikolay Viskov
3
我不知道你试图通过你的测试证明什么。你理解我的评论了吗?我的观点是,this[N]*(this + sizeof(this)*N)不等价的,但是在我看来,你原来的回答暗示它们是等价的。sizeof(this)是完全没有意义的,只是碰巧因为它与0相乘而起作用。但是对于除0以外的任何其他值的N,它都行不通。那么为什么你的公式中会有它呢? - Benjamin Lindley
2
指针和整数相加已经按指向的对象的大小进行了扩展。this [0]恰好与*(this + sizeof(this)* 0)相同,但this [N]*(this + sizeof(this)* N)相同;相反,它等效于*(this + N)(这是N * sizeof * this字节的对象,或更简单地说,是在this指向的位置之后N个元素)。在任何情况下,sizeof(this)无关紧要;它提供的是指针的大小,而不是指向的对象的大小。 - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接