为何超出内存限制?

时间:2016-11-14 10:27:57

标签: c++ c++11

我在Leetcode OJ上做了“按频率排序字符”问题。 任何人都可以向我解释为什么会这样吗?

class Solution {

public:
    struct Node {
        int freq;
        char ch;
    };

    static bool lambda(struct Node a, struct Node b){
        return a.freq>b.freq;
    }

    string frequencySort(string s) {
        if(s.size() == 0)
            return "";

        string res = "";
        vector<Node> nums(256);

        for(char c : s){
            nums[(int)c].ch = c;
            nums[(int)c].freq++;
        }

        std::sort(nums.begin(), nums.end(), Solution::lambda);

        char c;
        for(int i=0; nums[i].freq > 0; i++){
            c = nums[i].ch;
            while(nums[i].freq--){
                res = res + c; // If I replace this line with res += c, it gets Accepted!
            }
        }

        return res;
    }
};

1 个答案:

答案 0 :(得分:6)

res = res + c; // If I replace this line with res += c, it gets Accepted!

string operator+(string&, string&)运算符将参数复制到新的字符串对象中。然后,将此临时返回值复制到res - 这可能还涉及复制到新的更大的缓冲区。除非启用了C ++ 11,否则将使用移动分配,因此可以避免后一个可能的分配+复制。

string& operator+=(const string&)不会创建新的字符串对象。它会就地修改现有的字符串缓冲区 - 除非需要更大的缓冲区,否则无法避免重新分配。

因此,res += c避免在动态内存中创建临时缓冲区。如果字符串足够大,则同时使用的副本数量加倍可以使程序的峰值内存使用量大约翻倍。此外,额外的临时分配可能会增加动态内存空间的碎片,这会增加动态内存管理的开销。这两个因素可能会导致超出程序的内存限制。