关于c++:test笔记

3次阅读

共计 8365 个字符,预计需要花费 21 分钟才能阅读完成。

语句

语句根底

常见类别

表达式语句:表达式后加分号

​ 表达式求值,后抛弃

​ 可能产生副作用

    2 + 3; // 表达式;

    int x;
    x = 3;  // 表达式求值,返回值 x 后抛弃
            // 副作用:x 值的扭转

空语句:仅蕴含一个分号的语句

    罕用在循环体
    

复合语句(语句体):{……} 结尾无分号

{
    int x = 3;
    x+=1;
    std::cout << x << "\n";
}    // 一条复合语句
    // 造成独立的域(语句域)// 域中可定义长期变量, 准确管制生命周期
    
{...};// 两条语句 ; 为空语句
int x = 2;
{
    int x = 3;
    x++;
}

程序语句与非程序语句

程序语句

语义上依照先后顺序执行
理论的执行程序可能产生变动,编译器优化 / 硬件乱序执行等
与硬件流水线紧密结合,执行效率较高

非程序语句

在执行过程中引入跳转,产生简单变动
** 分支预测 ** 晋升性能,预测谬误可能导致执行性能升高
会限度编译器优化

goto

通过标签指定跳转地位
限度:不能跨函数跳转
    向前(下)跳转时,不能越过初始化语句
向后跳转可能导致对象的销毁与从新初始化

goto 实质对应汇编中的跳转指令
    不足结构性的含意
    容易造成逻辑凌乱
    防止应用
int main()
{
    int x = 1;
    if(x) goto label;
    x++;
label:
    return 0'
}

分支语句

非程序语句分为分支语句与循环语句

if 与 switch

if

if (){} else { } 双分支
if (){} else {if (){} else{} }多分支
if (){} else   if (){} else{ }  省去大括号 等价

else 会与最近的 if 进行匹配

int grade = 65;
if (grade > 60)
    if(grade >80)
        std::cout << "Excellent\n";
else                            // 缩进有效,与第二个 if 匹配
    std::cout <<"Bad\n";

应用大括号明确 防止匹配谬误,

constexpr if
c++17 开始可退出 constexpr
编译期优化

constexpr int grade = 59;
if constexpr(grade <60)
{std:cout <<"fail \n";}
else
{
    std::cout <<"pass\n";
    if constexpr (grade == 100)
    {std::cout << "excellent \n";}
    else
    {std::cout << "not bad \n";}
}

带初始化语句的 if(c++17)

int x = 3;
if(int y = x*3; y>100)    // y 作用域到 else 完结
{//......}
else
{//......}

switch

条件:任何整型或枚举类型,或可按语境隐式转换到整型或枚举类型的表达式
语句:任何语句。case: default: break;

case/default 标签

case: 跟常量表达式,匹配 switch 中条件,匹配执行后续
break: 防止 fall through
    -Wimplicit-fallthrough 产生编译正告
default: 地位任意,放前边留神加 break
int x ;
switch(std::cin >> x; x)// 可选初始化 (c++17)
{
    case 2+1:
        std::cout<<"3\n";
        break;
}

case/default 定义对象必须加{}

case 1:{
    int x = 1;
    
    break;
}

共享逻辑

switch(std::cin >> x; x)
{
    case 4:case 5://expression
        break;
}

[[falthrough]]属性 (c++17)

switch (x)
{
    case 1:
        //......
        [[fallthrough]];// 表明的确不须要 break;
    case 2:
        //......
        break;
}

switch 与 if 比照

switch 能做的 if 都能够,反之不肯定
switch 肯定水平上可在通过跳转进行优化,运行期效率比 if 更高

循环语句

对一系列语句重复执行

while/do while

条件:任何能按语境转换为 bool 的表达式,或带花括号或等号初始化器的单个变量的申明
语句:任何语句,它是循环体

while(int x = 3)// 等号初始化器,返回 3
                // 每次循环都会初始化
{
    std::cout << x << std::endl;
    --x;
}

不蕴含额定的初始化内容(for 循环蕴含初始化,不会反复初始化)

do while

条件:不能带花括号或等号初始化表达式(do 未初始化)结尾加分号

for

正式语法:
attr(可选) for(初始化语句 条件(可选);迭代表达式(可选))语句
非正式语法:
attr(可选) for(申明或表达式(可选); 申明或表达式(可选); 表达式(可选))语句

初始化语句:一条表达式语句(可为空;)一条简略申明,通常为带初始化器的循环计数变量的申明,能够任意多个变量
条件:可按语境转换到 bool 的表达式。每次循环 之前 反复求值
迭代表达式:任何表达式。每次循环 之后 反复求值, 通常为循环计数器表达式
语句:任何语句。作为循环体
for(int i = 0, *p = &i;i < 9; i+=2)    // 能够申明多个名字
                                    // 只有它们能用领有雷同的申明说明符序列
                                    // 根底类型不能扭转
{std::cout <<i <<":"<<*p << " ";}
// 不倡议,会引入歧义
int* p,q;// p 为 int* q 为 int

for(int x = 0,double y = 0.1; ;)//error 
{}

for(; ;)    // 均可为空
            // 条件为空,主动判 true
//=======================================================            
char cstr[] = "Hello";        
for(int n = 0; char c = cstr[n]; ++n)// 遍历完 cstr 后 '\0' 返回 0
{std::cout << c;}
std::cout << "\n";
//=======================================================    
std::vector<int> v = {3,1,4,1,5,9};
for(auto iter = v.begin();iter != v.end();++iter)
{}
//=======================================================    
// 非典型应用
int n = 0;
for(std::cout << "循环开始 \n";
    std::cout << "循环测试 \n";                // 输入失常返回 true
    std::cout << "迭代" << ++n << '\n')
    if(n>1)
        break;
/*    
    循环开始
    循环测试
    迭代 1
    循环测试
    迭代 2
    循环测试
*/

基于范畴的 for 循环(range for loop)

C++11/17/20
语法:属性(可选)for(范畴申明:范畴表达式)循环语句

  属性(可选)for(初始化语句(可选)范畴申明:范畴表达式)循环语句  --c++20    

实质:语法糖,编译器转换为 for 循环模式

int main()
{std::vector<int> arr{1,2,3,4,5};
    for(int v : arr)
        std::cout << v << '\n';
}

range for 不同版本转换 / 解释

{
    auto && __range = range-expression ;// 范畴表达式
    for (auto __begin = begin_expr, __end = end_expr;// 首表达式,尾表达式 
        __begin != __end; ++__begin) {
        range-declaration = *__begin;// 范畴申明
        loop-statement                // 循环语句
    }
}

(until C++17)
//=================================================================
{    // 首表达式,尾表达式可能返回不同类型,c++17 通过离开申明解决
    auto && __range = range-expression ;
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for (; __begin != __end; ++__begin) {
        range-declaration = *__begin;
        loop-statement
    }
}
(since C++17)
(until C++20)
//=================================================================
{   //c++20 引入初始化语句,解决长期范畴表达式问题
    init-statement
    auto && __range = range-expression ;
    auto __begin = begin_expr ;
    auto __end = end_expr ;
    for (; __begin != __end; ++__begin) {
        range-declaration = *__begin;
        loop-statement
    }
}
(since C++20)
//=================================================================

// 长期范畴表达式
for(auto& x : foo().items()){/*......*/}// 行为可能不确定
// 若 foo 返回右值,可能被销毁,x 援用绑定生效,循环产生未定义的行为
//c++20 引入初始化语句解决
for(T thing = foo();auto& x : thing.items()){/*......*/}
//foo()产生的右值被保留到 thing 中,thing 生命周期到循环完结

应用常量左值援用读元素
应用“万能援用(universal reference)”批改元素

std::vector<std::string> arr{"h","e","l","l","o"};
for (const std::string& v : arr)// 应用常量左值援用,防止从新结构 string,更高效
                                //const auto& v : arr
    std::cout << v << '\n';
    
std::vector<bool> arr1{true,false,true};

for(auto& v : arr1) {}    //error bool 迭代器解援用不是 bool
for(auto&& v : arr1) {}    // 万能援用 

break/continue

break:
continue:
for (int j = 0; j < 2; j++) {for (int k = 0; k < 5; k++) {         // break 只会影响此循环
        if (k == 2) break;
        std::cout << j << k << " ";
    }
}
//00 01 10 11

for (int i = 0; i < 10; i++) {if (i != 5) continue;
    std::cout << i << " ";       // 每次 i!=5 时跳过此语句
}
std::cout << '\n';
 
for (int j = 0; j < 2; j++) {for (int k = 0; k < 5; k++) {   // continue 只会影响此循环
        if (k == 3) continue;
        std::cout << j << k << " "; // 每次 k==3 时跳过此语句
    }
}

break;continue; 不能用于多重嵌套循环
多重嵌套循环跳转思考应用 goto

for(int j = 0; j < 2; j++){for(int k = 0;k < 5;k++){if(k == 2) goto label;
        std::cout << j << k << " ";
    }
}
label:
//......

达夫设施

constexpr size_t buffer_count = 10000;
std::vector<size_t> buffer(buffer_count);
for(size_t i = 0;i< buffer_count;++i)
{buffer[i] = i;}

size_t max_value = buffer[0];
for(size_t i = 0; i < buffer_count; ++i)// 破费老本更多
{max_vlaue = (max_value > buffer[i]) ? max_value : buffer[i];
}
std::cout << max_vlaue << "\n";

//==============================================================
// 循环展开
for(size_t i = 0; i + 8 < buffer_count; i+=8)// 循环解决缩小,程序性能晋升
{max_vlaue = (max_value > buffer[i]) ? max_value : buffer[i];
    max_vlaue = (max_value > buffer[i+1]) ? max_value : buffer[i+1];
    max_vlaue = (max_value > buffer[i+2]) ? max_value : buffer[i+2];
    max_vlaue = (max_value > buffer[i+3]) ? max_value : buffer[i+3];
    max_vlaue = (max_value > buffer[i+4]) ? max_value : buffer[i+4];
    max_vlaue = (max_value > buffer[i+5]) ? max_value : buffer[i+5];
    max_vlaue = (max_value > buffer[i+6]) ? max_value : buffer[i+6];
    max_vlaue = (max_value > buffer[i+7]) ? max_value : buffer[i+7];
}
// 然而内存拜访越界
// 解决残余
for(size_t i = buffer_count / 8 *8;i< buffer_count;++i)
{max_vlaue = (max_value > buffer[i]) ? max_value : buffer[i];
}

//=======================================================================
// 指针优化,switch 优化
auto ptr = buffer.begin();
for(size_t i = 0; i + 8 < buffer_count; i+=8)
{max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
switch(buffer_count % 8)
{case 7:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 6:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 5:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 4:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 3:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 2:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
    case 1:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
//====================================================================
// 持续优化
switch(buffer_count % 8)
{case 0:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 7:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 6:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 5:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 4:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 3:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 2:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]]
case 1:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
for(size_t i = 0; i  < (buffer_count-1)/8; ++i)
{max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
}
//====================================================================
// 达夫设施 switch 套循环
size_t i = 0;
switch(buffer_count % 8)
    for(;i<(buffer_count+7)/8;++i)
    {[[fallthrough]];
    case 0:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 7:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 6:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 5:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 4:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 3:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 2:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;[[fallthrough]];
    case 1:max_value = (max_value > *ptr) ? max_value : *ptr; ++ptr;
    }
// 间接跳转到 for 外部,再触发循环
正文完
 0