補足03

本文介绍了C++中引用的概念及其使用方式,并通过实例对比了值传递与引用传递的区别。重点讲解了如何利用引用提高程序运行效率,尤其是在处理大型数据结构时的优势。

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

C++によるプログラミング入門補足3
参照(リファレンス)について

 こんにちは。今回は参照について説明します。(最近、説明がちょっと一本調子になっているようで、少し反省しています。)ただ、すべてを網羅的に説明することはできません。私がとても大事だと思うところだけ説明します。


 参照は英語のカタカナ読みでリファレンス(とかレファランス)などと言われることもあります。これは「別名」のことです、、、って別名ってなんでしょう。

 ここでちょっと問題です。次のプログラムを実行したらどうなるでしょう。考えてみてください。

//ref_sample0.cpp
#include <iostream>
using namespace std;

void func(int x)
{
    //xに5を足す
    x += 5;
}

int main()
{
    int v = 3;
    func(v);
    cout << v << endl;
}

 まず、funcという名前の関数を定義しています。(ここでは簡単のため、クラスのメンバではない関数、つまりグローバルな関数を例にしますが、クラスの関数でも同じです。)「x += 5;」は「xに5を足せ」という意味でしたね。
 mainの中では、vという変数を作り、そこに3を格納し、そのvをfuncに渡し、最後にvを表示させる、というものです。
 Cを知っている人は、なああんだ簡単、と思ったことでしょう。答えは画面に3と打出されるのです。8ではありません!この辺はC++のもとになったCという言語の特徴のひとつなのです。

 つまり、、、どういうことでしょう。つまり、func(v)で関数の内部に、vという変数そのものが渡されるのではなく、vの値3が(xに)コピーされて渡されるのです。CやC++ではそうなっているのです。こういうのを「値渡し」なんて言います。ちょっとかっこいいので、覚えておきましょう。コピーに5を足しても、もとのvの値は変わらないのです。

 ところが、次のようにfuncの定義を一個所だけ変えると、8と打出されるのです。

//ref_sample1.cpp
#include <iostream>
using namespace std;

void func(int& x)
{
    //xに5を足す
    x += 5;
}

int main()
{
    int v = 3;
    func(v);
    cout << v << endl;
}


おおー。

 vの値がfuncで変わったのは、funcの定義で、仮引数(関数内で引数を表すパラメータ)が「int x」から「int& x」になったところだけです。こうすると、func(v)としてときに、vの値3ではなく、vそのものがxという名前で関数内に与えられることになるのです。つまり、xはvと同じものになったのです。このとき「xはvの参照である」と言います。つまり、xはvの「別名」になったのです。

 ああ、こりゃ便利と思いましたか?初心者には別に感想はないかもしれませんね。こういうやり方で変数の値を変更すると、わかりづらいプログラムになるという人もいます。まあ、これはみなさんの判断におまかせしましょう。

 実は引数を参照にしてしまうひとつの利点は、効率にあります。つまり、引数が参照でない場合、渡された値をコピーする手間がかかるのに、参照の場合はその手間がないのです。
 扱っているものが上の例のようにintなんかでは、コピーの手間は問題になりません。しかし、引数がとても大きなデータ(たとえば画像データ)を持つクラスのオブジェクトであった場合、しかも、その関数が何度も呼ばれる場合、コピーの手間のせいで、プログラムの実行速度が遅くなることが考えられるのです。
 それは困ります。そういうときにも、参照が使われるのです。つまり、ある(大きな)データを表すクラスをThingとします。すると、

void func(Thing x){
  定義内容
}

より、

void func(Thing& x){
  定義内容

の方が(普通は)速いということです。(引数として与えるオブジェクトが、あらかじめ生成されていないと、それを生成する手間がかかり、効率的ではなくなります。)

 しかし、funcの中で、引数の内容を変えるつもりはない場合もあります。つまり、引数のデータは、それを使うだけで、変更するつもりがない場合です。そのようなときは、

void func(const Thing& x){
  定義内容

と書くわけです。こう書くと、「定義内容」の中で、xについて、const指定されていない(つまり、宣言・定義で後ろにconstのついていない)メンバ関数を呼び出すことはできなくなります。constについては、補足1、補足2も参考にしてください。


補足 C++入門6

 C++入門6の最後の補足で、neko3.cppのNekoクラスを

class Neko
{
private:
    string name;
public:
    Neko(string s) : name(s){}
    void naku(){
        cout<<"にゃあ。俺様は"<<name<<"だ。"<<endl;
    }
};

のように書くと、Borland C++コンパイラは

「値でクラスを渡す引数を持つ関数はインライン展開されない」

という警告します、と書きました。
 これは、Borland C++が「コンストラクタをインラインにできない」と判断し、警告を出しているのです。その理由は、コンストラクタの引数がクラス(今の場合、文字列を表すstring)のオブジェクトになっているからです。
 上に書いたように、C++の関数では、引数の値が仮引数にコピーされます。しかし、クラスのオブジェクトには「メモリをたくさん使う大きなもの」もあるでしょう。そのようなオブジェクトをコピーするのは効率が悪いので、Borland C++は、「引数の型がクラスの関数はインラインにしない」と判断しているのです。これは、コンストラクタであっても、別のメンバ関数であっても同じです。
 しかし、関数の引数を参照にすると(つまり、参照渡しにすると)、インライン化をし、警告を出さなくなります。それは、つまり、たとえば、次のようにすればよいわけです。

class Neko
{
private:
    string name;
public:
    Neko(const string& s) : name(s){}
    void naku(){
        cout<<"にゃあ。俺様は"<<name<<"だ。"<<endl;
    }
};

 コンストラクタの仮引数に、constを付けたのは、警告とは直接関係ありません。sの内容を変更するつもりがないので付けました。

基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。 智能教学辅助系统 这是一个智能教学辅助系统的前端项目,基于 Vue3+TypeScript 开发,使用 Ant Design Vue 作为 UI 组件库。 功能模块 用户模块 登录/注册功能,支持学生和教师角色 毛玻璃效果的登录界面 教师模块 备课与设计:根据课程大纲自动设计教学内容 考核内容生成:自动生成多样化考核题目及参考答案 学情数据分析:自动化检测学生答案,提供数据分析 学生模块 在线学习助手:结合教学内容解答问题 实时练习评测助手:生成随练题目并纠错 管理模块 用户管理:管理员/教师/学生等用户基本管理 课件资源管理:按学科列表管理教师备课资源 大屏概览:使用统计、效率指数、学习效果等 技术栈 Vue3 TypeScript Pinia 状态管理 Ant Design Vue 组件库 Axios 请求库 ByteMD 编辑器 ECharts 图表库 Monaco 编辑器 双主题支持(专业科技风/暗黑风) 开发指南 # 安装依赖 npm install # 启动开发服务器 npm run dev # 构建生产版本 npm run build 简介 本项目旨在开发一个基于开源大模型的教学实训智能体软件,帮助教师生成课前备课设计、课后检测问答,提升效率与效果,提供学生全时在线练习与指导,实现教学相长。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值