C++Primer阅读笔记-第9章-函数 形参

本文深入探讨了C++中参数传递机制,包括基本类型、指针、const引用等场景下的实参与形参交互特性,以及引用形参在函数调用中的应用与局限性,特别强调了大型对象传递的复制成本问题。通过具体代码示例,清晰展示了不同参数传递方式对内存操作的影响。

参数传递
非引用形参
非引用类型的形参是通过复制对应的实参实现初始化(实参副本来初始化形参),函数内部无法修改实参
本身,只能修改局部的副本值。

1:指针形参
函数的形参是指针类型,也是用实参的指针副本来初始化形参,改变形参指针的指向地址不会影响到外
面的实参,但是如果函数内形参和外面实参的指针都是指向同一个内存地址,那么修改形参指针指向内
存地址的值,将会影响到实参。

int v=4;
void Fun(int *p)
{
    cout<<*p<<endl;//输出5
    *p=11;
    cout<<*p<<endl;//输出11,这里修改了形参指针指向地址的值,地址和实参指针指向的地址是同一个,所以函数外面打印这个地址的值是11
    p=&v;
    cout<<*p<<endl;//输出4,这里修改了形参指针指向的地址,只作用于局部副本,实参指向的地址没有改变

}
int main()
{
    int i=5;
    int *p=&i;
    cout<<*p<<endl;//输出5
    Fun(p);
    cout<<*p<<endl;//输出11
    system("PAUSE");
    return 0;
}

2:const形参
函数使用是非引用的非const或const形参,实参可以是const或者非const,因为这里传递的是实参的副
本给非引用的形参。

void fun(int i)//非引用非const形参
{
    i+=1;//这里可以修改形参
    cout<<i<<endl;
}
void fun1(const int i)//非引用const形参
{
    //i+=1;//形参是const,所以函数内部无法修改
    cout<<i<<endl;
}
int main()
{
    int i=1;
    const int j=2;
    fun(i);//传递实参i的副本,输出2
    fun(j);//传递实参j的副本,输出3
    fun1(i);//传递实参i的副本,输出1
    fun1(j);//传递实参j的副本,输出2
    system("PAUSE");
    return 0;
}

3:复制实参的局限性
-无法实现修改实参的值
-大型对象作为实参传递时,复制对象付出的时间和存储空间代价过大


引用形参
引用形参是直接关联到其所绑定的对象,而并非这些对象的副本。
下面例子是查找vector中与给定值相同的元素个数和返回指向该元素的迭代器

#include <iostream>
#include <vector>
using std::cout;
using std::endl;
using std::vector;

vector<int>::const_iterator fun(
    vector<int>::const_iterator beg,
    vector<int>::const_iterator end,
    int value,
    vector<int>::size_type &count
    )
{
    vector<int>::const_iterator res=end;
    for(;beg!=end;beg++)
    {
        if(*beg==value)
        {
            if(res==end)//第一次找到值
                res=beg;
            count++;
        }
    }
    return res;
}
int main()
{
    vector<int> vec;
    vec.push_back(1);
    vec.push_back(3);
    vec.push_back(3);
    vec.push_back(6);
    vec.push_back(7);
    vector<int>::size_type count=0;
    vector<int>::const_iterator beg=fun(vec.begin(),vec.end(),3,count);
    cout<<count<<endl;
    system("PAUSE");
    return 0;
}

const引用
非const引用形参对类型等比较敏感,而const的引用形参调试过程中发现竟然很多地方都可以过。

void fun(int &i)
{
    i++;
    cout<<i<<endl;
}
void fun1(const int &i)
{
    cout<<i<<endl;
}
int main()
{
    double d=1.1;
    int i=1;
    const int j=2;
    //fun(d);//error 这里函数期待一个非const int类型的引用
    fun(i);//ok i是函数期待的非const int类型引用
    //fun(j);//error j是const,而函数期待非const
    fun1(d);// 搞不清楚为什么这里能编译通过
    fun1(i);//奇怪,这里也能通过
    fun1(j);//ok
    system("PAUSE");
    return 0;
}

string类型的非const引用形参需要注意字符面量作为实参

void fun(string &str)
{
    str+="!";
    cout<<str<<endl;
}
int main()
{
    string str("hello kenny");
    fun(str);
    //fun("hello jay");//error 这里字符面量是const char[10],函数要求非const引用
    system("PAUSE");
    return 0;
}

传递指向指针的引用
int *&v1就是一个指向指针的引用,从右至左理解:v1是一个引用,与指向int类型对象的指针相关联,
v1只是一个传递进函数的指针别名

//修改指针指向的地址,而地址的值不变
void fun(int *&v1,int *&v2)
{
    int *p=v2;
    v2=v1;
    v1=p;
}
//交换指针指向地址的值
void fun1(int *&v1,int *&v2)
{
    int p=*v2;
    *v2=*v1;
    *v1=p;
}
int main()
{
    int i=1;
    int j=2;
    int *v1=&i;
    int *v2=&j;
    cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2
    fun(v1,v2);
    cout<<"*v1="<<*v1<<" "<<"*v2="<<*v2<<endl;//2,1
    cout<<"i="<<i<<" "<<"j="<<j<<endl;//1,2 注意这里只是指针指向的地址交换,而i和j的值没变
    fun1(v1,v2);
    cout<<"i="<<i<<" "<<"j="<<j<<endl;//2,1 这里函数交换的是指针指向地址的值
    system("PAUSE");
    return 0;
}

转载于:https://www.cnblogs.com/kennyMc/archive/2012/11/26/2789533.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值