首页 > 解决方案 > 为什么我的程序在使用储备后没有加速?

问题描述

我写了两个函数。在第二个中,我使用了“保留”,因此没有内存重新分配,但不幸的是,第二个函数并不比第一个快。我写出了字符串地址,在第一个函数中有几次重新分配,但两个函数同时执行。

我认为它应该更快,我错了吗?

    string commpres2(string str)
    {
        string strOut;
        int count = 0;
        //int adress = 0;
        for (int i = 0; i < str.length(); ++i)
        {
            ++count;
            if (i < str.length() - 1)
            {
                if (str[i + 1] != str[i])
                {
                    strOut += str[i];
                    strOut += to_string(count);
                    /*if (adress != (int)&strOut[0])
                    {
                        adress = (int)&strOut[0];
                        cout << adress << endl;
                    }*/
                    count = 0;
                }
            }
            else
            {
                strOut += str[i] + to_string(count);
            }
        }
        return strOut.length() < str.length() ? strOut : str;
    }

    string commpres3(string str)
    {
        string strOut;
        strOut.reserve(7000000);
        int count = 0;
        //int adress = 0;
        for (int i = 0; i < str.length(); ++i)
        {
            ++count;
            if (i < str.length() - 1)
            {
                if (str[i + 1] != str[i])
                {
                    strOut += str[i];
                    strOut += to_string(count);
                    /*if (adress != (int)&strOut[0])
                    {
                        adress = (int)&strOut[0];
                        cout << adress << endl;
                    }*/
                    count = 0;
                }
            }
            else
            {
                strOut += str[i] + to_string(count);
            }
        }
        return strOut;
    }

    int main()
    {
        str = "aabcccccaaa";
        //str.size ~= 11000000;
        for (int i = 0; i < 20; ++i)
            str += str;
        commpres2(str); //8 543ms
        commpres3(str); //8 534ms
    }

您即将回答我的问题,但仍然缺少一些东西。下面是我的“commpres3”函数的完整版本:

    string commpres3(string str)
    {
        int compressedLength = 0;
        int countConsecutive = 0;
        for (int i = 0; i < str.length(); ++i)
        {
            ++countConsecutive;
            if (i + 1 >= str.length() || str[i] != str[i + 1]) 
            {
                compressedLength += 1 + 
                    to_string(countConsecutive).length();
                countConsecutive = 0;
            }
        }
        if (compressedLength >= str.length())
            return str;
        string strOut;
        strOut.reserve(compressedLength);
        //strOut.reserve(7000000);
        int count = 0;
        //int adress = 0;
        for (int i = 0; i < str.length(); ++i)
        {
            ++count;
            if (i < str.length() - 1)
            {
                if (str[i + 1] != str[i])
                {
                    strOut += str[i];
                    strOut += to_string(count);
                    /*if (adress != (int)&strOut[0])
                    {
                        adress = (int)&strOut[0];
                        cout << adress << endl;
                    }*/
                    count = 0;
                }
            }
            else
            {
                strOut += str[i] + to_string(count);
            }
        }
        return strOut;
    }

    int main()
    {
        str = "aabcccccaaa";
        //str.size ~= 11000000;
        for (int i = 0; i < 20; ++i)
            str += str;
        commpres2(str); //107ms //30,32% CPU
        commpres3(str); //147ms //42,58% CPU
    }

现在我使用了发布模式和这个 CPU 分析器。所以我的问题是:真的吗?通过一个字符串计算长度需要更长的时间,而不是在内存中移动这个字符串几次?

标签: c++string

解决方案


我不是这个概念的专家,但每次调用一个函数并获取它的值然后将它与“i”进行比较时,都在 for 循环中使用“i < str.length()”,这需要更多时间来处理你的循环。

所以为了防止这种情况,在你的“compress3”函数中,而不是每次你需要它时调用“str.length(),只需将它存储在一个整数中,比如”int len = str.length(); " 并且在你的循环中使用 "i < len" 而不是 "i < str.length()"。

你的代码应该是这样的:

string commpres3(string str)
{
    string strOut;
    strOut.reserve(7000000);
    int count = 0;
    //int adress = 0;
    int len = str.length();
    for (int i = 0; i < len; ++i)
    {
        ++count;
        if (i < len - 1)
        {
            if (str[i + 1] != str[i])
            {
                strOut += str[i];
                strOut += to_string(count);
                /*if (adress != (int)&strOut[0])
                {
                    adress = (int)&strOut[0];
                    cout << adress << endl;
                }*/
                count = 0;
            }
        }
        else
        {
            strOut += str[i] + to_string(count);
        }
    }
    return strOut;
}

推荐阅读