2017-01-18 3 views
0

У меня возникла какая-то странная проблема при выполнении на C++. Мой проект большой, где я использовал проход по ссылке в нескольких местах, но я показываю вам образец проблемы, которую вы можете легко протестировать.Странное поведение в C++ с разными версиями компилятора (String pass by reference): см. Простую иллюстрацию программы

Я написал эту простую программу и протестировал ее под версией GCC: v4.9.2 и v5.4.0. У меня другое поведение. при передаче std :: string с ссылкой и без ссылки. В этой программе я просто добавляю две записи в карту и нахожу значение для ключа. Проблема заключается в map :: find (..). Я ожидаю постоянного поведения независимо от используемой версии компилятора gcc.

GCC версии: 4.9.2 выход: НАЙДЕНО, FOUND (проверено на Raspberry PI3, http://cpp.sh)

GCC версии: 5.4.0 выход: НЕ НАЙДЕН, FOUND (проверено на Ubuntu v16.04)

Почему такой случай? Что-то не так с программой или что-то ошибка компилятора? Следующая программа должна компилироваться как есть.

// program.cpp 
// Compile using: "g++ -o program program.cpp" 

#include <iostream> 
#include <string> 
#include <map> 
#include <stdio.h> 
using namespace std; 

std::map<const char*,int> mymap; 

bool FindWithoutPassByRef(const std::string id_) 
{ 
    const char* id = id_.c_str(); 

    std::map<const char*, int>::iterator it; 
    it = mymap.find(id); 

    if (it != mymap.end()) 
    { 
     cout <<"FOUND"; 
     return true; 
    } 

    cout <<"NOT FOUND"; 
    return false; 
} 

bool FindWithPassByRef(const std::string& id_) 
{ 
    const char* id = id_.c_str(); 

    std::map<const char*, int>::iterator it; 
    it = mymap.find(id); 

    if (it != mymap.end()) 
    { 
     cout <<"\nFOUND"; 
     return true; 
    } 

    cout <<"\nNOT FOUND"; 
    return false; 
} 

int main(int argc, char *argv[]) 
{ 
    printf("gcc version: %d.%d.%d\n",__GNUC__,__GNUC_MINOR__,__GNUC_PATCHLEVEL__); 

    const std::string key1 = "key1"; 
    const std::string key2 = "key2"; 

    mymap[key1.c_str()] = 50; 
    mymap[key2.c_str()] = 60; 

    FindWithoutPassByRef(key1); // should print FOUND 
    FindWithPassByRef(key1); // should print FOUND 

    cout<< endl; 
} 

Я бы предпочел НАЙТИ и НАЙДЕНО в любом компиляторе gcc. См. Пример, выполняющийся под GCC v4.9.2 here, или добавьте вышеуказанный код на cpp.sh (используется v4.9.2). Для компилятора v5.4.0 вы можете проверить это на Ubuntu или в другом месте соответствующим образом.

+0

@slava, было бы неплохо, если бы вы могли поделиться ссылкой на сообщение вместе с обозначением его как дубликата. – Sammy

+0

Спасибо, получил его здесь (http://stackoverflow.com/questions/4157687/using-char-as-a-key-in-stdmap). Но этот пост не является дубликатом, так как мое сообщение относится к поведению с const char * как к ключу в карте + с непоследовательной работой в разных версиях компилятора. – Sammy

+1

Ссылка есть сверху, справа под объектом. Ваша проблема точно такая же: вы не используете правильный компаратор. – Slava

ответ

4

Вы помещаете указатели на карту и пытаетесь сопоставить их с другими указателями. Это сравнивает только «адрес памяти», удерживаемый этими указателями; он не сравнивает то, что они указывают (т. е. ваши строковые данные).

Когда ваши указатели являются указателями на данные из одного std::string, вероятность того, что они являются одинаковыми указателями (потому что данные находятся в одном месте), являются хорошими. Однако, когда ваши указатели имеют разные строки, вероятность этого очень мала.

Не ставьте char Указатели на картах. Вместо этого сравните фактические строки.

+1

Здесь может быть даже UB, потому что конструктор копирования не является функцией 'const', недействительным результатом' .c_str() '. Я бы не ожидал разницы в поведении здесь, но это может помочь объяснить, почему наблюдаемое поведение изменяется, по-видимому, из-за оптимизации копирования. На самом деле это не имеет никакого значения. Как я уже сказал, просто не делай этого! –

+0

Спасибо, это имеет смысл. Однако не могли бы вы рассказать мне, почему было бы непоследовательное поведение в разных версиях компилятора (как указано выше)? – Sammy

+1

@Sammy: Я мог бы, вероятно, разобраться в этом, но я не склонен тратить время на это, потому что в этом нет никакой ценности. Возможно, у кого-то еще больше времени, чтобы сэкономить :) –

 Смежные вопросы

  • Нет связанных вопросов^_^