[基础]C++:名字的作用域

使用表准库规范

#include <iostream>
using namespace std;
namespace print
{
    void Print(const int* a, const int* b)
    {
        while (a != b)
        {
            std::cout << *a++ << std::endl;

        }
    }
    void Print(const int* a, const size_t b)
    {
        for (size_t i = 0; i < b; i++)
        {
            cout << a[i] << endl;
        }
    }
}
int main()
{
    std::cout << "Hello World!\n";
    int j[2] = { 0,1 };
    print::Print(begin(j), end(j));//用到了标准库
    print::Print(j, end(j)-begin(j));//用到了标准库
}

传递多维数组

  • C++语言中实际上没有真正的多维数组,多为的多维数组实际上是数组的数组
void print (int max[][10],int rowSize){}

等价定义

void Print (int(*max)[10], int rowSize) {}

main:处理命令行选项

int main(int argc,char *argv[]){}

第二个形参argv是一个数组,它的原属是指向C风格的字符串指针,第一个形参argc表示数组中字符串的数量。也可以写成如下形式

int main(int argc,char **argv){}

当实参传递给main后,第一个元素指向程序的名字或者空字符串
之后传递命令行提供的参数

prog -d -o oflie data0
argv[0]="prog";
argv[1]="-d";
argv[2]="-o";
argv[3]="ofile";
argv[4]="data0";
argv[5]="0";

含有可变形参的函数

有时我们无法提前预知应该向函数传递几个实参。如果所有的实参类型相同,可以传递一个名为initializer_list的标准库类型;如果类型不同,可以编写一个特殊的函数,以后会讲到

  • initializer_list形参
    如果函数的实参数量未知,但是所有的类型相同。

void Error_Msg(initializer_list<string> il)
{
    for (auto beg = il.begin(); beg < il.end(); beg++)
    {
        cout << *beg << "";
        cout << endl;
    }
}
int main()
{
    std::cout << "Hello World!\n";
    Error_Msg({ "H","s","v" });//三个参数
    Error_Msg({ "R","G" });//两个参数
}

省略符参数

  • 省略符参数有两种形式:
void foo(parm_list,...)
void foo(...)

第一种形式指定了foo函数的部分形参的类型

返回类型

  • 不要返回局部对象的引用或指针
const string& mainip()
{
    string ret;
    if (!ret.empty())
    {
        return ret;//错误。返回局部对象的引用
    }
    else
    {
        return "Empty";//错误,返回一个局部临时变量
    }
}
int main()
{
    std::cout << "Hello World!\n";
    cout<<mainip()<<endl;
}

对于第一个return,显然它返回的是一个局部变量。第二个return中,字符串字面值转换成了一个局部临时变量,该对象和ret一样是局部的。

  • 引用返回左值
    调用一个引用的函数得到左值,其他返回类型得到右值。
char& get_val(string& str, string::size_type ix)
{
    return str[ix];
}
int main()
{
    std::cout << "Hello World!\n";
    string s("a value");
    cout << s << endl;//输出a value
    get_val(s, 0) = 'A';//将s[0]改成A
    cout << s << endl;//输出A value

}

列表初始化返回

  • 根据C++11的新规定,函数可以返回花括号包围的值的列表
vector<string> process()
{
    if (false)
    {
        return {};//返回一个空的vector对象
    }
    else
    {
        return { "A","B" };//返回列表初始化vector对象
    }
}
int main()
{
    std::cout << "Hello World!\n";
    vector<string> ss = process();

}

主函数main的返回值

  • main函数的返回值可以看作状态指示器,返回0表示执行成功。返回其他值表示执行失败
int main()
{
    std::cout << "Hello World!\n";
    if (true)
    {
        return EXIT_SUCCESS;//预处理变量直接使用

    }
    else
    {
        return EXIT_FAILURE;//预处理变量直接使用
    }

}

递归

  • 如果一个函数调用了它本身,不敢这个电泳是直接还是间接的,都叫这种函数为递归函数如下面求阶乘的方法:
int factorial(int cal)
{
    if (cal > 1)
    {
        return cal * factorial(cal - 1);
    }
    else
    {
        return 1;
    }
}
int main()
{
    std::cout << "Hello World!\n";
    cout<<factorial(5)<<endl;

}

函数将不断调用自身直到程序栈空间耗尽为止。

返回数组指针

  • 因为数组不能拷贝,所以函数不能返回数组。但是可以返回数组的指针或引用。最直接的方法是使用类型别名:
typedef int arrt[10];//arrt是一个别名,表示类型是含有10个整形的数组
using arrt=int[10];//等价的声明
arrt* func(int i); //返回一个指向含有10个整数的数组
  • 当然也可以不用类型别名:
int(*func2(int i))[10];

使用尾置返回类型

  • C++11中可以简化func声明。尾置返回类型在参数列表后面有一个->。为了表示真正的函数返回类型在后面。我们在前面加一个auto:
auto func(int i)->int(*)[10];
  • 使用decltype
    当我们知道返回的指针指向那个数组时,可以用decltype关键字声明
int odd[] = { 0,1,2,3,4 };
int even[] = { 1,2,3,45,4 };
//返回一个指针,该指针指向含有5个整数的数组
decltype(odd)* arrPtr(int i)
{
    return (i % 2) ? &odd : &even;//返回一个指向数组的指针
}

参考:C++primer 第五版

推荐阅读更多精彩内容