在哪里放"删除"在循环

时间:2014-12-24 14:17:29

标签: c++ delete-operator

假设我有以下代码:

int decreasingTest(int number){
int numberOfDigits = 0; do { number /= 10; numberOfDigits++; } while (number != 0);
int *arrayValue = new int[numberOfDigits + 1];
for(int i = numberOfDigits;0<=i;i--){ //acquire digits of number
    arrayValue[i] = (number - fmod(number, pow(10, i))) / pow(10, i);
    number = fmod(number, pow(10, i));
    i--;
}
for (int j = 0; j < sizeOfArray; j++){
    if (arrayValue[j + 1] <= arrayValue[j]){
        if ((j + 1) == sizeOfArray){
            cout << "The number's digits are decreasing." << endl;
            return 5;
        }
        continue;
    }
    return 0;
}

}

我应该将delete arrayValue[]放在return 0之前和continue之后的括号之后,行return 0之后,还是最后一个括号之前的行?< / p>

6 个答案:

答案 0 :(得分:6)

您的代码中有三个位置可以从函数返回:

  1. return 5
  2. 上 循环后的return 0
  3. 在结束括号之前,如果外部循环永远不会执行。
  4. 为了不泄漏资源,必须为执行的每个delete调用执行一次new调用。在您的情况下,由于您有两个返回点,您需要两个delete次呼叫 - 一个在每个返回点之前。

    在此处手动管理动态内存是有问题的。很容易忘记删除某些内容,尤其是当您有多个返回点时。已经构建了许多语言功能和库组件来解决此问题。像shared_ptrunique_ptr这样的智能指针会自动管理动态分配资源的销毁,因此您根本不需要编写deletemake_shared和{{ 1}}使你永远不会写make_unique。 (注意:new不在C ++ 11标准中,但它易于编写,并且应该符合C ++ 14标准。)

    由于多种原因,C-Style阵列本身也存在问题。其中最明显的是它们的固定大小和经常伴随它们的神奇数字。语言特性和库组件也存在以解决这些问题,我建议通常情况下(几乎)不应该使用C风格的数组。相反,请使用vector

    在您的情况下,您根本不需要指针。你只需要一个'vector&#39;:

    make_unique

答案 1 :(得分:4)

对于这种特殊情况,没有理由使用动态内存。不要试图迂腐,但动态内存会被许多不应该使用的地方使用。

[ADDENDUM(进一步的信息和对可能点的无耻抓取)]

您认为所需的位数已经存在于标准库中,因为十进制表示非常常见。以下是基于Hallvard Furuseth在Google Group comp.std.c中发布的帖子,但我没有从初始位大小计数中扣除符号位,因此它应该适用于有符号和无符号类型。 +3项是指存储因子所需的数字&#39; 1&#39; (LOG10(1)= 0);标志&#39; +&#39;或&#39; - &#39 ;;以及可能的空终止字符。因子146/485仅略大于log10(2)(等效于任何基数中的log(2)/ log(10)),这是从二进制到十进制表示的数字比例因子。如果您发现任何问题,请告诉我。

//Overestimate for number of decimal digits representing an integer of type integerType
//Works for both signed and unsigned integer types
//Includes space for sign ('+' or '-') and for a termination character
//Upper-bounds the function floor(log10(abs(n))) + 3

#define SIZEDIGITS(integerType) (((sizeof(integerType)*CHAR_BIT)*146)/485 + 3)

中int8_t: 5位数(&#39; +/- 127 \ 0&#39;)

uint8_t: 5位数(&#39; +255 \ 0&#39;)

APPROXIMATION给出(8 * 146)/ 485 + 3 = 5位

int16_t: 7位数(&#39; +/- 32767 \ 0&#39;)

uint16_t: 7位数(&#39; +65536 \ 0&#39;)

APPROXIMATION给出(16 * 146)/ 485 + 3 = 7位

int32_t: 12位数(&#39; +/- 2147483647 \ 0&#39;)

uint32_t的: 12位数(&#39; +4294967295 \ 0&#39;)

APPROXIMATION给出(32 * 146)/ 485 + 3 = 12位

的int64_t: 21位数(&#39; +/- 9223372036854775807 \ 0&#39;)

uint64_t中: 22位数(&#39; +18446744073709551615 \ 0&#39;)

APPROXIMATION给出(64 * 146)/ 485 + 3 = 22位

int128_t: 41位数

uint128_t: 41位数

APPROXIMATION给出(128 * 146)/ 485 + 3 = 41位

int9999_t(假装):3012位数

uint9999_t(假装):3012位

APPROXIMATION给出(9999 * 146)/ 485 + 3 = 3013(一个未使用的字节 - 人性!)

(您可能会或可能不会注意到的随机奖励事实:对于实数,我们通常的功率总和数字表示,base-e被认为是最有效的实数基数。三元在这方面优于二进制,因为它更接近e。)

答案 2 :(得分:2)

鉴于您现在拥有的代码结构,您需要将三个单独的位置放在delete [] arrayValue;命令中(注意,[]位于arrayValue之前,而不是之后) 。您需要将其放在return 5;上方return 0;正上方的行上,并在最后一个括号前面。代码可能会在这三行中的任何一行退出您的函数,在这种情况下,您应该在退出函数之前释放内存。

或者,你可以用int *arrayValue = new int[numberOfDigits + 1];替换行std::vector<int> arrayValue(numberOfDigits + 1),让编译器为你处理分配/释放。

答案 3 :(得分:1)

您也可以使用智能指针,例如std :: unique_ptr(http://en.cppreference.com/w/cpp/memory/unique_ptr),当指针超出范围时,它会自动释放动态分配的数组。

答案 4 :(得分:1)

  1. 最重要的一点是,几乎从来没有你应该new数组的情况。我强烈建议您在此处使用std::vector,这样您的int *arrayValue = new int[numberOfDigits + 1];就会变为: std::vector<int> arrayValue(numberOfDigits + 1); 而且您无需更改其他代码。

    请注意,在代码可能出错的情况下,例如你的某个pow s throws并且你离开这个函数而没有返回,std::vector仍然清理自己,这是不可能的可以说new ed memory。

  2. 如果您发现自己处于1%的情况下应该管理自己的记忆。一个好的经验法则是从不有多个return语句。它只会使您的代码难以理解且无法维护。所以你应该把你的最后一个循环改为:

    int result = 0;
    int j = 0;

    while(j < sizeOfArray - 1 && arrayValue[j + 1] <= arrayValue[j]){
    j++;
    }

    if (j == sizeOfArray - 1){
    cout << "The number's digits are decreasing." << endl;
    result = 5;
    }
    delete[] arrayValue;
    return result;

答案 5 :(得分:0)

应该使用标头std::unique_ptr中声明的标准智能指针<memory>。例如

std::unique_ptr<int[]> arrayValue( new int[numberOfDigits + 1] );

在这种情况下,您无需担心删除数组。