当前位置: 首页 > 知识库问答 >
问题:

这种代码行为是否定义明确?

金谭三
2023-03-14

下面是一些C代码:

#include <iostream>

class A
{
    int x;
    int y;
    double v;

    public:
        A(int x, int y)
            :x(x),y(y)
        {
            std::cerr << "A("<<x<<","<<y<<")\n";
        }
        ~A()
        {
            std::cerr << "~A()\n";
        }
        operator double* ()
        {
            v=1.5*x+y;
            return &v;
        }
};

void f(double* val)
{
    std::cerr << "f("<<*val<<")\n";
    *val=0.3;
}

int main()
{
    f(A(3,5));
}

我得到以下输出:

a(3,5)
f(9.5)
~A()

一、 因为我希望它能起作用。但我不确定在<code>f</code>返回后是否必须调用<code>A</code>的析构函数。有保证吗?运算符double*()返回的指针在调用f,是否会以某种方式变得无效?

共有2个答案

左丘嘉言
2023-03-14

函数的参数在调用函数之前进行求值,临时变量将一直存在到它们所在的完整表达式的末尾。因此,是的,A的实例将活到调用f

韦高格
2023-03-14

你声明了一个A对象作为f的实参,当你这样做的时候,对于所有的效果来说,这个新对象就像是f的一个局部变量,所以~A肯定会在f执行结束时被调用。

如果 f 返回由运算符 double* () 返回的地址,并且在 f 返回后使用它,您将访问无效内存。避免这种情况的一种方法是使double v成为静态的,但您必须考虑,在代码中,A类创建的对象仅在f块运行时退出。

 类似资料:
  • 这两个代码的行为都会在值不存在时引发异常。 我想知道这两个代码之间的区别。

  • 假设您知道您的软件只会在符号溢出行为定义良好的两台互补机器上运行。签名溢出在C和C中仍然是未定义的行为,编译器可以用“ret”替换整个程序,启动核战争,格式化驱动器,或者让恶魔从你的鼻子里飞出来。 假设您在内联 asm 中进行了签名溢出,您的程序是否仍会调用 UB? 如果是,那么单独编译和链接的汇编程序呢?

  • 问题内容: var x int done := false go func() { x = f(…); done = true } while done == false { } 这是Go代码。我的恶魔告诉我,这是UB代码。为什么? 问题答案: Go Memory Model不保证该程序将始终遵守在goroutine中写入x的值。go常规销毁 部分中提供了一个类似的错误程序作为示例。 在本节中,G

  • 我熟悉在一个账户和另一个账户之间转账时使用同步的并发示例,例如,两个账户的锁定是按账号顺序进行的,这样就不会发生死锁。 我想探索使用Reenter antReadWriteLock,因为在我看来,这将允许帐户对象的客户端进行并发读取,前提是没有客户端更新该对象。 我已经编写了代码并对其进行了测试,它似乎可以工作,但看起来有点难看,例如,Account类暴露其锁对象看起来有点奇怪,但它似乎必须这样做

  • 问题内容: 和 第二个代码产生了一个空指针异常,该怎么做才能使下一个等效? 问题答案: 我可以看到,如果players某个自定义java.lang.Iterable的get()实现的实现被破坏,或者至少以一种异常的方式(与的行为不同),就会发生这种情况。 除此之外,我唯一能想到的就是您未在代码中向我们展示的某些内容导致了某些错误。 如果执行此操作会怎样?

  • 在这个问题的启发下,我写出了测试题: 本程序以普通大小写形式打印: 首先:我解释这种行为是JIT编译器的存在。“预热”后,每个线程的JIT编译器缓存值非字段。对吧? 第二:如果先对或不对,我如何验证这一点? 附注。-我知道打印-选项。 更新:enviroment:Windows 7 64bit,JDK 1.7.0_40-b43(热点)。