函数返回对象时的问题

来看这个代码

#include <iostream>
#include <string>
#include <map>

std::map<std::string, std::string> mapHttpRequest;

std::string GetString(std::string strKey)
{
    std::map<std::string, std::string>::iterator it = mapHttpRequest.find(strKey);
    if (it != mapHttpRequest.end())
    {
        return it->second;
    }    
    return "";
}

int SplitString()
{
    std::string strUrlParamValue = GetString("l");
    std::cout<<"before: "<<strUrlParamValue<<std::endl;
    char *pInOuter;
    char* p = strtok(const_cast<char*>(strUrlParamValue.c_str()), "|_");
    while (p)
    {
        std::cout<<"-> "<<p<<std::endl;
        p = strtok(NULL, "|_");
    }
    std::cout<<"after: "<<strUrlParamValue<<std::endl;
    return 0;
}

int main()
{
    mapHttpRequest["l"] = "4001|4002";
    SplitString();
    SplitString();
    return 0;
}

一般理解,连续调用两次 split string 函数,输出应该是完全一致的吧,嗯,来看结果

before: 4001|4002
-> 4001
-> 4002
after: 40014002
before: 40014002
-> 4001
after: 40014002

环境是 linux 2.6.16 64bit,gcc 的版本是 4.1.2

不过,在 vs 2005 下跑这个代码,得到的输出确实这样的

before: 4001|4002
-> 4001
-> 4002
after: 4001 4002
before: 4001|4002
-> 4001
-> 4002
after: 4001 4002

嗯,这个跟想象中的差不多吧

把细节打出来看看呗

#include <iostream>
#include <string>
#include <map>

std::map<std::string, std::string> mapHttpRequest;

std::string GetString(std::string strKey)
{
    std::map<std::string, std::string>::iterator it = mapHttpRequest.find(strKey);
    if (it != mapHttpRequest.end())
    {
        std::cout<<"map value addr: "<<(void*)it->second.c_str()<<std::endl;
        return it->second;
    }    
    return "";
}

int SplitString()
{
    std::string strUrlParamValue = GetString("l");
    std::cout<<"get string func return addr: "<<(void*)strUrlParamValue.c_str()<<std::endl;
    std::cout<<"before: "<<strUrlParamValue<<std::endl;
    char *pInOuter;
    char* p = strtok(const_cast<char*>(strUrlParamValue.c_str()), "|_");
    while (p)
    {
        std::cout<<(void*)p<<" -> "<<p<<std::endl;
        p = strtok(NULL, "|_");
    }
    std::cout<<"after: "<<strUrlParamValue<<std::endl;
    return 0;
}

int main()
{
    mapHttpRequest["l"] = "4001|4002";
    SplitString();
    SplitString();
    return 0;
}

先看 linux 下的结果

map value addr: 0x504098
get string func return addr: 0x504098
before: 4001|4002
0x504098 -> 4001
0x50409d -> 4002
after: 40014002
map value addr: 0x504098
get string func return addr: 0x504098
before: 40014002
0x504098 -> 4001
after: 40014002

再看 vs 2005 的执行结果

map value addr: 005D345C
get string func return addr: 0018FDF8
before: 4001|4002
0018FDF8 -> 4001
0018FDFD -> 4002
after: 4001 4002
map value addr: 005D345C
get string func return addr: 0018FDF8
before: 4001|4002
0018FDF8 -> 4001
0018FDFD -> 4002
after: 4001 4002

其中的原因,有可能是编译器的返回值优化,也有可能是 stl 的各自实现不同,现在过年了,没心情细究啊。。

Leave a Reply

Your email address will not be published. Required fields are marked *