C++ Primer 第七章 函数

本文详细解析了C++中函数的多种特性,包括返回类型、参数传递、返回值、函数声明、局部对象及内联函数的用法,并深入探讨了类的成员函数与重载函数的概念。同时,文章提供了关于指向函数的指针和函数指针形参的实例,以及如何在C++中有效利用这些高级功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

①函数不能返回另一个函数或者内置数组类型,但可以返回指向函数的指针,或指向数组元素的指针的指针
②函数的参数传递:   
   1.传值得局限性: 
      当需要在函数中修改实参的值时。   
      当需要以大型对象作为实参传递时。对实际的应用而言,复制对象所付出的时间和存储空间代价往往过在。       
      当没有办法实现对象的复制时。    
    2.引用形参:利用const引用避免复制

// compare the length of two strings
bool isShorter(const string &s1, const string &s2)
{
    return s1.size() < s2.size();
}

    3.传递指向指针的引用

//   swap values of two pointers to int
     void ptrswap(int *&v1, int *&v2)
     {
         int *tmp = v2;
         v2 = v1;
         v1 = tmp;
     }

定义应从右至左理解:v1 是一个引用,与指向 int 型对象的指针相关联。

    4.Vector和其他容器类型的形参:从避免复制vector 的角度出发,应考虑将形参声明为引用类型。事实上,C++ 程序员倾向于通过传递指向容器中需要处理的元素的迭代器来传递容器

    // pass iterators to the first and one past the last element to print
     void print(vector<int>::const_iterator beg,
                vector<int>::const_iterator end)
     {
         while (beg != end) {
             cout << *beg++;
             if (beg != end) cout << " "; // no space after last element
         }
         cout << endl;
     }

    5.数组的形参:

      1.以下是三种等价的定义方式:

    // three equivalent definitions of printValues
     void printValues(int*) { /* ... */ }
     void printValues(int[]) { /* ... */ }
     void printValues(int[10]) { /* ... */ }


      2.编译器忽略为任何数组形参指定的长度

       3.通过引用传递数组,如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。在这种情况下,数组大小成为形参和实参类型的一部分。编译器检查数组的实参的大小与形参的大小是否匹配。

 // ok: parameter is a reference to an array; size of array is fixed
     void printValues(int (&arr)[10]) { /* ... */ }
     int main()
     {
         int i = 0, j[2] = {0, 1};
         int k[10] = {0,1,2,3,4,5,6,7,8,9};
         printValues(&i); // error: argument is not an array of 10 ints
         printValues(j);  // error: argument is not an array of 10 ints
         printValues(k);  // ok: argument is an array of 10 ints
         return 0;
     }

    4.多维数组的传递:

// first parameter is an array whose elements are arrays of 10 ints
     void printValues(int (matrix*)[10], int rowSize);

     我们也可以用数组语法定义多维数组。与一维数组一样,编译器忽略第一维的长度,所以最好不要把它包括在形参表内:

   // first parameter is an array whose elements are arrays of 10 ints
     void printValues(int matrix[][10], int rowSize);
   

     5.传递给函数的数组的处理:

       使用标准库规范
      

   void printValues(const int *beg, const int *end)
     {
         while (beg != end) {
             cout << *beg++ << endl;
          }
     }
     int main()
     {
         int j[2] = {0, 1};
         // ok: j is converted to pointer to 0th element in j
         //     j + 2 refers one past the end of j
         printValues(j, j + 2);
         return 0;
     }

     显示的传入数组的长度:

    // const int ia[] is equivalent to const int* ia
     // size is passed explicitly and used to control access to elements of ia
     void printValues(const int ia[], size_t size)
     {
          for (size_t i = 0; i != size; ++i) {
              cout << ia[i] << endl;
          }
     }
     int main()
     {
         int j[] = { 0, 1 }; // int array of size 2
         printValues(j, sizeof(j)/sizeof(*j));
         return 0;
     }

       6.main: 处理命令行选项   

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

第二个形参 argv 是一个 C 风格字符串数组。第一个形参argc 则用于传递该数组中字符串的个数。

③函数的返回值:

 1.void表示没有返回值,此时不用在函数内部添加return,或者添加return;。

 2.返回非引用的类型:函数的返回值用于初始化在调用函数处创建的临时对象用函数返回值初始化临时对象与用实参初始化形参的方法是一样的。如果返回类型不是引用,在调用函数的地方会将函数返回值复制给临时对象。当函数返回非引用类型时,其返回值既可以是局部对象,也可以是求解表达式的结果。

   // return plural version of word if ctr isn't 1
     string make_plural(size_t ctr, const string &word,
                                    const string &ending)
     {
         return (ctr == 1) ? word : word + ending;
     }


 3.返回引用的类型:当函数返回引用类型时,没有复制返回值。相反,返回的是对象本身。千万注意:不能返回局部变量的引用。

    // find longer of two strings
     const string &shorterString(const string &s1, const string &s2)
     {
         return s1.size() < s2.size() ? s1 : s2;
     }

形参和返回类型都是指向 const string 对象的引用,调用函数和返回结果时,都没有复制这些 string 对象。


 4.引用返回左值:

  char &get_val(string &str, string::size_type ix)
     {
         return str[ix];
     }
     int main()
     {
         string s("a value");
         cout << s << endl;   // prints a value
         get_val(s, 0) = 'A'; // changes s[0] to A

         cout << s << endl;   // prints A value
         return 0;
     }

   如果不希望引用返回值被修改,返回值应该声明为 const

const char &get_val(...

  5. 千万不要返回指向局部对象的指针: 一旦函数结束,局部对象被释放,返回的指针就变成了指向不再存在的对象的悬垂指针。


④函数的声明:

  1.函数的声明也可以和函数的定义分离;一个函数只能定义一次,但是可声明多次。

  2.函数也应当在头文件中声明,并在源文件中定义。
⑤局部对象:

  1.局部变量的生命期局限于所在函数的每次执行期间。只有当定义它的函数被调用时才存在的对象称为自动对象。自动对象在每次调用函数时创建和撤销。

  2.形参也是自动对象。形参所占用的存储空间在调用函数时创建,而在函数结束时撤销。

  3.静态局部对象(Static Local Objects):当定义静态局部对象的函数结束时,静态局部对象不会撤销。

  size_t count_calls()
     {
          static size_t ctr = 0; // value will persist across calls
          return ++ctr;
     }
     int main()
     {
         for (size_t i = 0; i != 10; ++i)
             cout << count_calls() << endl;
         return 0;
     }


⑥内联函数(inline):inline避免函数调用的开销。

inline const string &
     shorterString(const string &s1, const string &s2)
     {
             return s1.size() < s2.size() ? s1 : s2;
     }


头文件中加入或修改 inline 函数时,使用了该头文件的所有源文件都必须重新编译。


⑦类的成员函数:

bool same_isbn(const Sales_item &rhs) const
         { return isbn == rhs.isbn; }

  1.const成员函数不能修改调用该函数的对象。因此函数 same_isbn 只能读取而不能修改调用它们的对象的数据成员。

   2.构造函数和初始化列表:

   Sales_item(): units_sold(0), revenue(0.0) { }


⑧重载函数:函数名相同,函数的参数不一样的才能进行重载

⑨指向函数的指针:

typedef bool (*cmpFcn)(const string &, const string &);
该指针类型为“指向返回 bool 类型并带有两个 const string 引用形参的函数的指针”。

   cmpFcn pf1 = 0;             // ok: unbound pointer to function
     cmpFcn pf2 = lengthCompare; // ok: pointer type matches function's type
     pf1 = lengthCompare;        // ok: pointer type matches function's type
     pf2 = pf1;                  // ok: pointer types match

通过指针调用函数
     cmpFcn pf = lengthCompare;
     lengthCompare("hi", "bye"); // direct call
     pf("hi", "bye");            // equivalent call: pf1 implicitly dereferenced
     (*pf)("hi", "bye");         // equivalent call: pf1 explicitly dereferenced

函数指针形参
void useBigger(const string &, const string &,
                    bool(const string &, const string &));
     // equivalent declaration: explicitly define the parameter as a pointer to function
     void useBigger(const string &, const string &,
                    bool (*)(const string &, const string &));









   




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值