默认参数中的 C++ new 运算符及其副作用

bat*_*ger 2 c++

我有一个关于 C++ 中默认参数的问题。如果我有这样的功能:

int foo(int* obj = new Int(4)) {
    /* Stuff with obj. */
}
Run Code Online (Sandbox Code Playgroud)

当然,现在整数仅用作示例,但问题是我是否要为参数提供一个值,如下所示:

int x = 2;
foo(&x);
Run Code Online (Sandbox Code Playgroud)

obj = new Int(4)即使我为参数提供了一个值并因此分配了我无法再读取的内存,该表达式是否仍会被计算?

Pet*_*ter 5

使用new表达式作为参数的默认值,如

 int foo(int *obj = new int(4));
Run Code Online (Sandbox Code Playgroud)

这是一个非常糟糕的主意,因为可能存在彼此行为不一致的用例,以及许多可能出现的不良结果。

假设,为了讨论的目的,执行foo()确实

 delete obj;
Run Code Online (Sandbox Code Playgroud)

如果调用者执行以下任一操作,那就没问题

 foo();             //  default argument is a new expression
 foo(new int(2));
Run Code Online (Sandbox Code Playgroud)

但如果调用者执行以下一项或多项操作,则会导致未定义的行为;

 foo(&some_int);      //  some_int is a variable local to the caller
 foo(new int[2]);     //   dynamically allocates an array
Run Code Online (Sandbox Code Playgroud)

相反,我们可以说这foo()不可行 delete obj。在这种情况下,这些陈述中的任何一个

 foo();
 foo(new int(3));
 foo(new int [2]);      // dynamically allocates an array
Run Code Online (Sandbox Code Playgroud)

导致内存泄漏,并且

  foo(&some_int);
Run Code Online (Sandbox Code Playgroud)

可能会正常工作(假设foo()不会以其他方式调用未定义的行为)。

真正的问题是foo()无法(在标准 C++ 的范围内)检测调用者执行了上述哪一项操作。因此,存在未定义行为或内存泄漏的真正风险,除非调用者完全做了“正确的事情”(其中“正确的事情”意味着不会导致内存泄漏或未定义的行为)。而且,由于有更多的选择来做错误的事情,调用者很可能不会做完全正确的事情。请记住,程序员在阅读文档方面是出了名的糟糕,因此依靠文档来确保调用者(或在调用者中编写代码的程序员)执行避免上述问题所需的操作是一个糟糕的方法。