分类目录归档:C++

C++14关联容器set自定义排序函数报错

十年前写的一个C++项目编译报错:“bool compatetor_asc::operator ()(const std::wstring &,const std::wstring &)”: 不能将“this”指针从“const compatetor_asc”转换为“compatetor_asc &”

对应的代码如下 :

class compatetor_asc
{
public:
    bool operator()(const std::wstring& lhs, const std::wstring& rhs) 
    {
        return lhs < rhs ;
    }
};

这段代码重载了函数调用操作符(),可以让该类的对象能够像函数一样使用。调用的代码std::set<std::wstring, compatetor_asc> m_OriginalAsc;

当时这个C++项目是用VS2008开发的,C++标准是C++03,现在用VS2022来编译,用的C++标准是C++14。

简单解了一下,原来从C++11开始,标准库排序谓词函数就要求必须是const成员函数了,那么只要把operator()函数改为const成员函数即可。

bool operator()(const std::wstring& lhs, const std::wstring& rhs) const
{
    return lhs < rhs ;
}

修改后再次编译,问题解决。

后记:

已经有近十年没有写过C++项目了,最初学习C++用的是VC++6.0,标准是C++98,到后来有了C++03,现如今已经到了C++23了,二十年如一梦。

std::string 常用函数

string replace(const string & str , const string & src , const string & dest )
{
        string ret;
       
        string:: size_type pos_begin = 0;
        string:: size_type pos       = str.find( src);
        while (pos != string::npos)
       {
              cout << "replacexxx:" << pos_begin <<" " << pos <<"\n";
              ret.append( str.data() + pos_begin, pos - pos_begin);
              ret += dest;
              pos_begin = pos + 1;
              pos       = str.find( src, pos_begin);
       }
        if (pos_begin < str.length())
       {
              ret.append( str.begin() + pos_begin, str.end());
       }
        return ret;
}

int split(const string & str , vector <string >& ret_, string sep = ",")
{
        if ( str.empty())
       {
               return 0;
       }
       
        string tmp;
        string:: size_type pos_begin = str.find_first_not_of( sep);
        string:: size_type comma_pos = 0;
       
        while (pos_begin != string::npos)
       {
              comma_pos = str.find( sep, pos_begin);
               if (comma_pos != string::npos)
              {
                     tmp = str.substr(pos_begin, comma_pos - pos_begin);
                     pos_begin = comma_pos + sep.length();
              }
               else
              {
                     tmp = str.substr(pos_begin);
                     pos_begin = comma_pos;
              }
              
               if (!tmp.empty())
              {
                      ret_.push_back(tmp);
                     tmp = "";
              }
       }
        return 0;
}


string trim(const string & str )
{
        string:: size_type pos = str.find_first_not_of( ' ');
        if (pos == string::npos)
       {
               return str;
       }
        string:: size_type pos2 = str.find_last_not_of( ' ');
        if (pos2 != string::npos)
       {
               return str.substr(pos, pos2 - pos + 1);
       }
        return str.substr(pos);
}

gdb的感性认识

编译时要加调试函数(-g): g++ -g hello.cpp -o hello

l: 列出代码
break 2: 在第2行加断点
break func:设置断点,在func()函数入口处
info break:查看断点信息
r: 运行程序(run的简写)
n: 单条语句执行(next)
c: 继续向下执行(continue)
p i: 答应变量i的值(print)
bt: 查看函数堆栈
finish: 退出函数

关于c++中const成员函数

const对象只能访问const成员函数,而非const对象可以访问任意的成员函数,包括const成员函数.

class CTest
{
public:
    CTest(const CTest& t) // 这里t是const修饰的类的引用,它所调用到的方法应该是const成员函数
    {
        a = t.Fun(); 
    }
    int Fun()  // const成员函数
    {
        return a;
    }
private:
    int a;
};
int main()
{
    return 0;
}

关于C++指针的引用

注意,只有指针的引用(*&)

没有引用的指针这么一说,引用的指针(&*)编译也是绝不可能通过的

指针的引用,代码如下:

#include <iostream>
using namespace std;
class A
{
public:
    int m_a;
};
void f(A * &a)
{
    cout << (a)->m_a << endl;
}
int main()
{
    A a;
    a.m_a = 88;
    A *p = &a;
    f(p);
    return 0;
}

分析的时候从右向左分析
f(A * &a)
先是 & , 表明这是一个引用
然后是 *
表明这是一个指向 A* 的引用

C++中ostringstream和istringstream的理解

今天脑子抽风,突然分不清ostringstream为什么叫输出, istringstream为什么叫输入.

抽过之后,做出如下总结,以防再抽.

输入输出是针对std::string而言的
输出流:格式化以后输出到std::string
输入流:绑定std::string str之后把str里的一个word输入到另一个std::string中,用于处理字符串

总结: 输入输出,站在流本身的角度来看。

温故而知新,函数指针

 函数指针:

一个函数在编译时被分配一个入口地址,这个入口地址就是函数指针.可以用一个指针变量指向该函数指针,然后通过该变量来调用函数.

声明:

返回值类型 (*指针变量名)(参数类型列表);

typedef 返回值类型 (*指针变量名)(参数列表名);