【问题标题】:Why it's possible to access std::unique_ptr<A>* u1 as u1[1000] and it still works [duplicate]为什么可以访问 std::unique_ptr<A>* u1 作为 u1[1000] 并且它仍然有效[重复]
【发布时间】:2020-08-28 22:50:35
【问题描述】:

对不起,愚蠢的标题,想不出它应该是怎样的。 我在玩 unique_ptr,创建了指向 unique_ptr 的指针(我知道我不应该创建指向 unique_ptr 的指针,我只是想看看发生了什么)

class A
{
  public:
    A() {std::cout<<"A const\n";}
    ~A() {std::cout<<"~A dest\n";}
    void fun()  {std::cout<<"A fun\n";}

};

int main()
{
   std::unique_ptr<A>* u1 = new std::unique_ptr<A>(new A);
   u1[1000]->fun();
   delete u1;
   return 0;
}

我预计输出会崩溃,但它就像我使用 u1[0] 时一样工作。我完全不知道为什么,我完全希望它崩溃。

A const
A fun
~A dest

这段代码是怎么执行的? 它适用于 g++,也适用于在线 c++ shell http://cpp.sh/

【问题讨论】:

标签: c++ arrays c++11 pointers unique-ptr


【解决方案1】:

从技术上讲,u1[1000]-&gt;fun(); 表现出未定义的行为,因此,“任何事情都可能发生”。

实际上,您使用无效的this 指针执行A::fun(),并且由于A::fun() 没有引用任何成员变量或虚函数,因此您可以侥幸逃脱。这可能是坏消息,而不是好消息,因为你有一个 bug 正在等待发生。

【讨论】:

    【解决方案2】:

    这段代码是怎么执行的?

    因为程序的行为是未定义的。

    无法保证程序会崩溃,也无法保证不会崩溃。对这种行为没有任何保证。

    我预计输出会崩溃

    当行为未定义时,您不能依赖程序以您期望的方式运行。


    int* t= 新的 int(10); t[1] = 1000;从不工作。这里我也期待

    你怎么知道它“从不工作”?您是否观察过每个已编写的程序的每次执行,用过去和未来的每个编译器的每个版本编译,有和没有编译器必须提供的所有各种选项,在现有的每个系统上?我怀疑你没有。即使我们假设你有,也不能保证它会按照你期望的方式运行。

    这个程序“从不工作”的意义与问题中的程序“从不工作”相同。行为未定义,任何事情都可能发生。它可能:

    • 总是崩溃
    • 永不崩溃
    • 有时会崩溃
    • 运行时崩溃,但其他人运行时不会崩溃
    • 总是有特定的输出
    • 永远不会有这样的输出
    • 有时会有这样的输出
    • 总是没有输出
    • 永远不会有任何输出
    • ...

    这个列表是无限的。

    我认为在大多数情况下即使是 UB 也有一些解释,比如在我的情况下为什么它没有崩溃

    在 C++ 中没有答案。您必须阅读编译器生成的汇编语言程序并询问“为什么这个汇编程序会崩溃”,然后可以在您的 CPU 和操作系统的手册中找到答案。

    【讨论】:

    • mm,我的意思是在第 t[1] = 1000 行之后,t[0] 永远不会是 1000。这就是我的意思“从不工作”的意思。在这我已经明白代码可以工作并且没有崩溃,因为 fun() 与这里的静态函数非常相似,所以它只需要类型,而不是实际对象,因为它不访问任何字段并且不是虚拟的。
    • @SimpleAsk 即使您确实访问了字段,或者该函数是虚拟的,也不能保证它会崩溃。也不能保证显示的不访问字段的程序不会崩溃。行为未定义。没有什么是保证的。就语言而言,任何事情都可能发生。
    • @SimpleAsk in duplicate 我指出它清楚地描述了为什么您没有在代码中观察到粉碎。请注意,事实(无论是看到预期输出的事实)都不会使您的程序正确或工作。这是 C++ 灵活性和强大功能的不幸代价。
    • @Slava 是的,我已经读过了,谢谢!当然我知道我应该依赖这样的东西,只是我认为在大多数情况下即使是 UB 也有一些解释,比如在我的情况下为什么它没有崩溃(至少在大多数情况下没有崩溃),现在我明白了为什么.
    • @SimpleAsk“只是我认为在大多数情况下即使是UB也有一些解释”恐怕你想错了。 UB 只有一种解释——语言标准是这样说的。看起来您在代码中混合了 UB 并观察到了行为。
    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 2013-04-12
    • 2016-08-06
    • 1970-01-01
    • 1970-01-01
    • 2019-01-05
    • 2012-04-29
    • 2019-06-12
    相关资源
    最近更新 更多