【问题标题】:How is possible that accessing nullptr works? [duplicate]访问 nullptr 怎么可能工作? [复制]
【发布时间】:2016-06-13 13:51:11
【问题描述】:

我有一个简单的课程:

class B
{
public:
    int getData() { return 3; }
};

然后,我用 nullptr 初始化一个指向它的指针:

B *foo{ nullptr };

然后,尝试使用它会带来惊喜:

int t = foo->getData();

而 t 现在是 3。如果不构造类,这怎么可能?是因为 getData() 不使用“this”吗?这打破了我对指针的所有知识。

这是预期的行为吗?我在 Visual Studio 2013 中工作。

【问题讨论】:

  • 之所以有效,是因为foo->getData() 等价于getData(foo);,并且被调用者从不取消引用参数。请注意,即使它有效,它在 C++ 中也被归类为 未定义的行为
  • 感谢大家的回答。在我看来,它不应该是未定义的行为,它应该崩溃。从我的角度来看,这是安全问题。如果一个方法接收到一个类的指针并且这个指针是nullptr,我可以使用这个指针来调用一个方法。是的,我知道不能保证它会起作用,但它是你图书馆的一个洞。
  • LeDYoM: "在我看来它不应该是未定义的行为,它应该崩溃。" 请对语言有耐心,阅读 C++ 的设计目标和一点它的历史。
  • @Nawaz 我喜欢 C++ 并且我理解它为什么有效。但这让我很惊讶。这个“特性”违反了你的类可能需要的不变量。是的,有人可以说“如果你不使用这个指针就没有不变量”,但我正在开发一个系统,我在其中断言一个类共享指针不是 nullptr,断言工作,但程序继续(在调试中)并且它工作,所以 assert(class != nullptr) 没用。但我假设这种行为来自 C。我仍然喜欢 C++,让我们在 C++17 中改进它;)
  • LeDYoM:这不是 C++ 中的真正想法。这个想法是允许编译器假设“有符号整数溢出永远不会发生”和“被取消引用的指针具有合法值”。如果您想在取消引用空指针时发生崩溃,那么您应该明确断言它是有效的。如果一些程序没有在这样的事情上不必要地分支,它们的运行速度会快很多倍——在 C++ 中,你不需要为不使用的东西付费,而且大多数程序员不想为此付费,所以在 C++17 中移除这种特殊的未定义行为是不可能的。

标签: c++ c++11 visual-studio-2013 nullptr


【解决方案1】:

这是预期的行为吗?

不,是UB,一切皆有可能。

是因为getData()没有使用“this”吗?

是的,它可能会起作用,因为this 不会在特殊情况下使用,但没有任何保证。

【讨论】:

  • 预期行为与未定义行为并不互斥。这正是我所期望的行为。
【解决方案2】:

undefined behavior,所以你真的应该很scared

显然它可能会发生某些事情(在您的 C++ 实现中),因为 getData 函数不是虚拟的,并且不使用 B 的任何成员。所以生成的代码不会取消引用空指针。

【讨论】:

    【解决方案3】:

    这是未定义的行为,您正在从nullptr 访问成员方法。不会定义任何特定的行为或结果。

    在这种情况下;给定(cppreference):

    关键字this是一个prvalue表达式,它的值是被调用成员函数的对象的地址。

    由于 thisNULL 值没有被取消引用 - 成员方法不是虚拟的并且不访问 this 的任何成员数据 - 它“似乎”工作。

    【讨论】:

    • 您是否知道任何可以定义行为的条件,例如constexpr/inline/const/noexcept getData(),聚合/POD/空类等?您的任何见解将不胜感激。
    • 我能想到的只有static,因为它取消了this 指针。
    • 我想我在想我在 en.cppreference.com/w/cpp/language/expressions#Discarded-value_expressions 中看到的东西,以及关于 prvalues 和临时实现的相关页面。但是有更多的讨论here 来支持你所说的。就我个人而言,当我需要一个假设的对象并且基本上从不使用 nullptr 时,我会使用 std::declval,但无论如何我可能需要考虑它们。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2019-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-22
    • 2022-11-24
    • 2019-04-08
    • 2015-03-11
    相关资源
    最近更新 更多