Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如果(!this){return false;}_C++_Null_This - Fatal编程技术网

C++ 如果(!this){return false;}

C++ 如果(!this){return false;},c++,null,this,C++,Null,This,我偶然发现了这段代码,这段代码对我来说似乎已经完全崩溃了,但它确实发生了这段是空的。我只是不明白这怎么可能是空的 它位于一个普通的方法调用中,例如 myObject->func(); 在MyObject::func()内部,我们有 if (!this) { return false; } 有没有办法让第一行抛出一个NullPointerException,而不是进入null(?)方法?如果您有: MyObject *o = NULL; o->func(); 接下来会发生什么取

我偶然发现了这段代码,这段代码对我来说似乎已经完全崩溃了,但它确实发生了
这段
空的
。我只是不明白这怎么可能是空的

它位于一个普通的方法调用中,例如

myObject->func();
MyObject::func()内部,我们有

if (!this) { return false; }
有没有办法让第一行抛出一个
NullPointerException
,而不是进入
null
(?)方法?

如果您有:

MyObject *o = NULL;

o->func();
接下来会发生什么取决于
func
是否是虚拟的。如果是,那么它将崩溃,因为它需要一个对象来获取vtable。但,若它不是虚拟的,则调用将继续,并将该指针设置为NULL

我相信标准说这是“未定义的行为”,所以任何事情都可能发生,但典型的编译器只是生成代码,不检查指针是否为空。一些著名的库依赖于我描述的行为:MFC有一个名为
SafeGetHandle
的函数,可以对空指针调用该函数,在这种情况下返回空

您可能需要编写一个可重用的助手函数:

void CheckNotNull(void *p)
{
    if (p == NULL)
        throw NullPointerException();
}
然后,您可以在函数开始时使用它来检查其所有参数,包括
this

CheckNotNull(this);

只有在对已删除对象调用方法时,或者如果某个对象正在写入不应该写入的内存(尤其是覆盖对象的this指针),才会出现this==null


您应该调查代码的真正错误,而不是像这样试图解决它。

在以下情况下,此指针可能会变为空:

class Test
{

public:
    bool f();

private:
    int m_i;
};


bool Test::f()
{
    if(!this)
    {
        return false;
    }

    m_i = 0;
    return true;

}


int main(int argc, char **argv)
{
    Test* p = new Test;
    delete p;
    p = NULL;

    p->f();
}

我想有人做了一个快速的黑客来避免访问冲突异常。

这可能是空的。我怀疑这段代码试图(严重地)检测竞争条件,其中对象尚未完成初始化或已被删除。

(this==NULL)根据标准是未定义的行为。我想你应该删除这张支票:)

假设我们进行以下调用:

((CSomeClass*) 0)->method();
行为已经没有定义,那么为什么还要在CSomeClass::method中检查这个==NULL呢

编辑:
如果您不使用成员变量,我假设您的编译器将处理(0==这个),但是它会在哪里找到虚拟表指针?在这种情况下,您的类不能使用polymoprhism。

捕获此类错误的方法(通过设计)是使用指针包装类(类似于
共享的\u ptr
),该类在创建时使用空指针参数抛出。取消引用时它也可能抛出,但这有点晚了——我想总比什么都没有好。

我以为first boost::shared\u ptr会抛出。但是在查找之后,我不得不删除我的答案,因为它不是row:(显然,它取决于实现是否抛出了某些内容。但是,在我的GCC中,我得到了一个断言失败-总比没有好:)将检入的一个原因是正确地执行标准,如果你的编译器没有为你做这件事,我一开始不会调用NULL,那么根本不需要检查。或者-当我检查时-然后在通话时间。当来电者做了这些不可能的事情时,为什么被来电者要担心呢?在这种情况下,一个好的智能指针包含一个assert是可以的,我认为是的,assert(obj)在代码中(而不是在方法中)或智能指针中可以帮助我们检测问题。总的来说,我看到很多开发人员不知道什么事情永远不应该发生,应该断言什么事情应该检查。。。取消引用NULL是标准中未定义的行为。MFC真的不应该依赖于此。如果它是实现定义的,事情就不同了。很可能这是一次“修复”竞争条件的拙劣尝试。故事的另一个寓意是:实现CheckNotNull并让它抛出一个异常,并显示消息“别做混蛋,鲍勃!”说真的,CLR在对空指针调用方法时抛出是有原因的——因为人们经常(意外地)抛出一个异常编写不遵守标准的代码。C++方法是让这些代码具有未定义的行为。如果你想要更好的东西,就把你自己的支票放进去。我认为最好断言(this!=0);这个故事告诉我们不要检查这个==NULL,也不要检查&ref==NULL,因为这不可能是真的。有一次一个组件没有检查,你的无效代码就会发疯。你不能更改“this”。这是右值。(=“this”不是对象)。你可以这样想,想象“self”就是这个指针:T*self\uuux=this#定义自我(self+0)//你做不到(self+0)=…啊,你是对的。我想说“但是它不能写成”。为什么要对这个空进行两次测试?“如果(这个)”不是有效的C++或java——如果你在某处有“y~定义空0”,它也可以是C++。java和java也必须是“抛出新的NulLoPosiExistAuto()),这是Java中的预定义异常。但在C#中不是这样,C#中有NullReferenceException。这是特定于.net的吗你可能想改变标签,很多C++用户会被过滤掉。NETNULLPOTExtExct让我相信这根本不是C++问题。C#?我只是很惊讶,当它试图呼叫f。。。我的意思是,如果p为NULL,p->任何东西都应该是seg fault。。。
((CSomeClass*) 0)->method();