cpp tips

string 14&17

  • cpp 使用s和sv可以使字符串包含\0而不被阶段
    • 需要使用命名空间std::string_literals;
      1
      2
      3
      4
      5
      6
      7
      8
      //在cpp 11后不被允许,将一个字符串常量赋值给一个char*
      char* s="ssss";//Error
      char cc="sssss"[0];
      const char* ="sss";
      std::string_literals;
      std::string p="sss"s;//字符串常量值,是一个string的类
      std::string_view q="qqqq"sv;//字符串可以修改 是string_view
      std::string tt = "sss"; //右侧是 常量字符串,可以赋值是因为背后是char *

auto int& register int

  • auto int 表示将变量存储到内存中
  • register int 表示将变量存储到 寄存器中
    1
    2
    3
    register int b;
    //由于寄存器没有地址,所以这样使用b 会被编译器放到内存中
    int c = &b;

extern&static&inline

code

1
2
3
4
5
static int x,y;//模块作用域,仅在当前文件内可以访问到,初始值为0
int main(){
static int y; //局部静态变量,初始值为0
return ::y+x+y;//分别访问模块静态变量y,模块静态变量x,局部静态变量y;
}

例子

访问外部模块变量

1
2
3
4
5
6
7
8
9
//main.cpp
#include <iostream>
using namespace std;

int main(){
extern int x;
int y=x;
return 0;
}
1
2
//A.cpp
int x=3;

访问外部模块变量

  • extern

    访问外部变量,既main()外部定义的变量,可以使全局变量也可以是模块变量

1
2
3
4
5
6
7
8
9
//main.cpp
#include <iostream>
using namespace std;
static int x=4;
int main(){
extern int x; //就近原则 x=3 是全局的,static int x=4 访问本模块的
int y=x;//x=4
return 0;
}
1
2
//A.cpp
int x=3;

测试
1
2
3
4
5
6
7
8
9
10
11
12
13
//main.cpp
#include <iostream>
using namespace std;
static int x=4;
int main(){
int x=5;
{
extern int x;
int y=x;//x=4
}

return 0;
}
1
2
//A.cpp
int x=3;

const&volatile&constexptr&inline

  • const

    • const 修饰变量

      • 本程序不修改,需要在定义时初始化
    • const 修饰函数(一定是成员函数),是否含有const 可以区分不同的重载

      const object non-const object
      const member function (保证数据成员不变) 可以 可以
      non-const member functions (不保证数据成员不变) 不可以 可以
      • const 修饰的函数,会被const 对象调用,当一个函数只有const版本,只可以被const对象调用
  • volatile

    • 本程序不修改,其他程序修改
    • 编译器不会优化,因为值时刻在变化。
  • constexptr

    • 将计算尽量放在编译阶段
    • 初始化要用常量表达式初始化
    • 常量表达式的计算是在编译时,才是常量表达式
    • 由于跟踪入参和函数结果,如果使用常量调用,可以提前计算
  • inline

    • inline 作用域就在当前模块,相当于默认加了static
    • 用于优化,可能变量不存在,变为
    • 对于函数,将调用展开
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
const volatile int z=3; //可以的
constexpr y=z;//不可以
const y=z;//可以

constexpr y=5;
y++;//不可以修改



constexpr int y=3+sizeof(printf("%d",x));
// 由于printf 函数返回时int类型,顾sizeof(int) 为固定值4;所以是常量表达式
//没有输出,因为constexpr 是在编译的时候做的计算
//sizeof不可以重载因为是在编译阶段进行计算

constexpr int f(int x){ //不修饰返回值,修饰入参和内容。用于优化
return x*x;
}

void main(){
int y = f(3); // 优化为int y =9;
}


constexpr 不表示返回值不可修改

1
2
3
4
5
6
7
8
9
10
constexpr int& f(int& x){
x=x*x;
return x;
}
int main(){
const volatile int z=0;
int x=5;
f(x)=9;
std::cout<<x<<std::endl; //x=9
}
inline
例子
1
2
3
4
5
6
7
8
//main.cpp
#include <iostream>
using namespace std;
inline int x=4;
int main(){
int y=x; // int y = 4;
return 0;
}
1
2
//A.cpp
int x=3;

  • 下列代码显示重复定义
    1
    2
    3
    4
    5
    6
    7
    8
    //main.cpp
    #include <iostream>
    using namespace std;
    int x=4;
    int main(){
    int y=x;
    return 0;
    }
1
2
//A.cpp
int x=3;

改进 1

可以正常编译通过

1
2
3
4
5
6
7
8
//main.cpp
#include <iostream>
using namespace std;
static int x=4;
int main(){
int y=x;
return 0;
}
1
2
//A.cpp
int x=3;
改进 2

可以正常编译通过

1
2
3
4
5
6
7
8
//main.cpp
#include <iostream>
using namespace std;
inline int x=4;
int main(){
int y=x;
return 0;
}
1
2
//A.cpp
int x=3;
改进 3

可以正常编译通过

1
2
3
4
5
6
7
8
//main.cpp
#include <iostream>
using namespace std;
inline int x=4;
int main(){
int y=x;
return 0;
}
1
2
//A.cpp
inline x=3;
外部函数
  • 编译失败,因为inline 相当于static 外部模块访问不到
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //main.cpp
    #include <iostream>
    using namespace std;
    inline int x=4;
    inline int f(){
    return 0;
    };

    int main(){
    int y=x;
    return 0;
    }
1
2
3
4
5
6
//A.cpp
inline x=3
extern int f();
int g(){
return f();
}
  • 修正
1
2
3
4
5
6
7
8
9
10
11
12
//main.cpp
#include <iostream>
using namespace std;
inline int x=4;
int f(){
return 0;
};

int main(){
int y=x;
return 0;
}
1
2
3
4
5
6
//A.cpp
inline x=3
extern int f();
int g(){
return f();
}