关于运营商的评估顺序 - >和()

时间:2015-09-26 05:10:20

标签: c++ c++11 language-lawyer operator-precedence

请考虑以下代码段:

std::shared_ptr<...> p = ...;
p->f(std::move(p));

根据cpprefoperator ->()具有相同的优先级,并且都是从左到右关联的。所以我假设p->std::move()之前被评估,并且片段应该没问题。但是VC15却反其道而且崩溃了我的程序。这是一个VC15错误还是我在这里遇到了错误?

1 个答案:

答案 0 :(得分:3)

您正在调用未定义的行为,因为函数调用中参数的求值顺序是而不是由标准指定,并且使用...

p->f(std::move(p));

您传递了两个参数。首先,this,其次是std::move(p)。但现在,有一个不那么明显的问题。你 写入同一个共享指针。这可能导致基本上任何东西,也称为未定义的行为。我们甚至没有提到你在这样的指针上使用std::move() ......

*this指向*p,但第一个(显式)参数现在保存指针本身,因此*p无效!让我们假设这并没有使程序崩溃(不知怎的......)。然后,一旦f离开,这可能导致对象本身被破坏。但是......当共享指针(假设只剩下一个引用)并且因此对象本身被销毁时,该函数仍然没有 。再一次,只是问题......

这只是一个例子,任何事情都可能发生在任何事情的中间。只是写在同一个表达式中你就可以了:)。

BTW We all know VS is all but standards-complaint,但无论如何,这与运营商解析的顺序和优先级无关。

修改:一切都很好如果 f()采用通用引用(又名:转发参考,又名崩溃-rvalue-reference-black-magic-that -somehow-got-into-the-standard)或右值参考。所以,例如......

void f(std::shared_pointer<...> &&ptr)

只要你不用ptr做错事,>

但是,如果f接受类型为std::remove_reference_t<decltype(*p)>>的对象,则共享指针会移到其参数上,并且所有上述内容都会发生。