经验一、map[key] 会向map插入一条空记载
unordered_map<string, string> map;
map.emplace("key1", "value1");
map.emplace("key2", "value2");
cout<<"value="<<map["key3"]<<endl;
auto iter = map.find("key3");
if (iter != map.end()){
cout<<"key3 found!"<<endl;
}else{
cout<<"key3 not found!"<<endl;
}
cout<<"value="<<map["key3"]<<endl;
运转成果:
value=
key3 found!
value=
key3竟然能在map中经过find函数查到。
正确的用法是:
C++里,map[key] 只能用于存值,不能用于取值。
文档如下:假如key不存在,则插入一条记载,值为默认值。
举一个经典的场景, 统计一个字符串数组里每个字符串呈现的次数,正确做法是:
unordered_map<string, int> map;
string array[] = {"a", "a", "b", "c", "c", "c"};
for (string item : array) {
if (map.find(item) != map.end()) {
map[item]++;
} else {
map[item] = 1;
}
}
cout << "{";
for (auto it = map.begin(); it != map.end(); it++) {
cout << "\"" << it->first << "\": " << it->second;
if (next(it) != map.end()) {
cout << ", ";
}
}
cout << "}" << endl;
运转成果:
{"c": 3, "a": 2, "b": 1}
经验二、 C++里的 getter 办法或许会产生值复制:
猜猜下面的代码会输出什么?:
class Test{
public:
Test() {
cout<<"list real address = "<<&list<<endl;
}
private:
vector<string> list;
public:
void addToList(const string & item){
list.emplace_back(item);
}
vector<string> getList(){
return list;
}
vector<string> & getListPointer(){
return list;
}
};
inline string listToString(const vector<string> & list){
string result = "{";
for(const auto & str : list){
result += str + ", ";
}
if (!list.empty()) {
result.pop_back();
result.pop_back();
}
result = result + "}";
return result;
}
inline void test1() {
Test t;
t.addToList("1");
const auto list1 = t.getList();
const auto & list2 = t.getList();
const auto list3 = t.getListPointer();
const auto & list4 = t.getListPointer();
cout << "list1 address: " << (&list1) <<", value=" <<listToString(list1) << endl;
cout << "list2 address: " << (&list2) <<", value=" <<listToString(list2) << endl;
cout << "list3 address: " << (&list3) <<", value=" <<listToString(list3) << endl;
cout << "list4 address: " << (&list4) <<", value=" <<listToString(list4) << endl;
}
输出:
list real address = 0x7ffeee78a8e0
list1 address: 0x7ffeee78a900, value={1}
list2 address: 0x7ffeee78a920, value={1}
list3 address: 0x7ffeee78a940, value={1}
list4 address: 0x7ffeee78a8e0, value={1}
也就是说,只要list4才是原地址,别的3种都产生了值的复制,都创建了新的list。假如list里的内容较多,或许就会严重影响功能。
经验三、bool 类型的默认值或许不是 false,int 的默认值或许不是0
class Test{
public:
Test() {}
public:
bool a{};
int b;
bool c;
};
inline void test1() {
Test t;
cout << "a: " << (t.a ? "true" : "false") << endl;
cout << "b: " << (t.b ) << endl;
cout << "c: " << (t.c ? "true" : "false") << endl;
}
int main() {
test1();
return 0;
}
履行成果:
a: false
b: 1907956496
c: true
a和c同为bool,初始化方式不一样,导致其值也不一样。b的类型是int,其默认值并不是0。
主张:做好初始化!
经验四、不要忽略 IDE 的正告:
string foo(){
return "xxxx";
}
const char *c1 = foo().c_str(); //这种用法看上去没问题吧
但IDE给出了正告:
经验五、函数没写回来值,IDE也不会报错(起码Clion没有报错)
int test(int a){
cout<<"a="<<a<<endl;
}
int main() {
test(1);
}
这样的代码在 Ubuntu 上确实可以履行成功, 但是在别的 Linux 平台, 或许会呈现难以排查的内存过错!
主张经常使用IDE的代码查看工具“Code -> Inspect Code”查看下代码:
待续。