引用与指针的关系,转换
先指一处书中的错误。
《c++ primer plus》第8章的代码片段。
free_throws &clone(free_throws &ft)
{
// free_throws *pt;
// *pt = ft;
// return *pt;
// 原书代码
// 修改后的代码
free_throws *pt;
pt = &ft;
return *pt;
}
实在不清楚弄个空指针,然后往内存里赋值是在干啥。而且这段代码还不是让你运行的代码,是个例子代码,初学者我估计都得搞疯,有很大误导性。回到正题吧
1. c++引用
查阅了网上资料,c++引用的本质还是变量,有地址、有值。但是在编译阶段被处理掉了,coding的时候简化了。
2. 引用与指针的对应
如前述代码
free_throws &clone(free_throws &ft)
{
free_throws *pt; // 定义指针变量;
pt = &ft; // ft的地址赋值给指针
return *pt; // 返回*pt, *pt等于ft。但是函数返回值为引用,怎么回事?
}
打印地址看看
free_throws &clone(free_throws &ft)
{
// free_throws *pt;
// *pt = ft;
// return *pt;
using std::cout;
free_throws *pt;
pt = &ft;
using std::cout;
cout << "pt address: " << pt << '\n';
return *pt;
}
three address: 0x16dc6f620
pt address: 0x16dc6f620
地址相同。赋值阶段是符合预期。这部分是正常的指针操作。
关键就在
return *pt;
这行。
返回的*pt===ft,这中间的替换从代码层面,类似与
void foo()
{
int a = 5;
int *b = &a;
int &c = *b;
std::cout << c << '\n';
}
正常打印:5
能看出来引用是在变量所在的内存位置插个带类型的旗子(这样的描述主要是为了与指针做区分),然后直接使用变量“值”和“地址”。
引用是不能像指针一样做强制类型转换的。
void foo1()
{
int a = 5;
long &b = a;
}
//8.6.strtref.cpp:108:11: error: non-const lvalue reference to type 'long' cannot bind to a value of unrelated type 'int'
long &b = a;
^ ~
1 error generated.
macos下编译不通过。从这个角度看,使用上不如指针灵活,但是更安全和方便。
3. 总结
- 引用不如指针灵活
- 由于限制条件,使用上会更加安全
- 在指针和引用转换、赋值的时候,一定不要被指针误导,只需要明确指针指向的值是什么即可。
4. 所有测试代码:
#include <iostream>
#include <string>
struct free_throws
{
std::string name;
int made;
int attempts;
float percent;
};
void display(const free_throws &ft);
void set_pc(free_throws &ft);
free_throws &accumulate(free_throws &target, const free_throws &source);
free_throws &clone(free_throws &ft);
void foo();
int main()
{
free_throws one = {"Ifelsa Branch", 13, 14};
free_throws tow = {"Andor Knott", 10, 16};
free_throws three = {"Minnie Max", 7, 9};
free_throws four = {"Whily looper", 5, 9};
free_throws five = {"Long Long", 6, 14};
free_throws team = {"Throwgoods", 0, 0};
free_throws dup;
set_pc(one);
display(one);
accumulate(team, one);
display(team);
display(accumulate(team, tow));
accumulate(accumulate(team, three), four);
display(team);
dup = accumulate(team, five);
std::cout << "Displaying team: \n";
display(team);
std::cout << "Displaying dup after assignment: \n";
display(dup);
set_pc(four);
accumulate(dup, five) = four;
std::cout << "Displaying dup after ill-advised assignment:\n";
display(dup);
using std::cout;
cout << "three address: " << &three << '\n';
free_throws &jolly = clone(three);
cout << "Displaying jolly :\n";
display(jolly);
foo();
return 0;
}
void display(const free_throws &ft)
{
using std::cout;
cout << "Name: " << ft.name << '\n';
cout << " Made: " << ft.made << '\t';
cout << "Attempts: " << ft.attempts << '\t';
cout << "Percent: " << ft.percent << '\n';
}
void set_pc(free_throws &ft)
{
if (ft.attempts != 0)
ft.percent = 100.0f * float(ft.made) / float(ft.attempts);
else
ft.percent = 0;
}
free_throws &accumulate(free_throws &target, const free_throws &source)
{
target.attempts += source.attempts;
target.made += source.made;
set_pc(target);
return target;
}
free_throws &clone(free_throws &ft)
{
// free_throws *pt;
// *pt = ft;
// return *pt;
using std::cout;
free_throws *pt;
pt = &ft;
using std::cout;
cout << "pt address: " << pt << '\n';
return *pt;
}
void foo()
{
int a = 5;
int *b = &a;
int &c = *b;
std::cout << c << '\n';
}
void foo1()
{
// int a = 5;
// long &b = a;
}

浙公网安备 33010602011771号