cpp 函数参数使用引用和const引用的区别(如string和const string&)

在c++中,&代表引用传递,跟指针的作用是一致的,只不过语法上做了一点点修改。
c++中函数参数如果是类对象一般使用&来修饰,从而避免不必要的构造和析构。
例如

class A{ };
void func(A&) { }

使用A&可以避免调用 A(A&) 来创建临时对象和 ~A() 来销毁临时对象。

看下面代码

void func(string& ) { }

int main() {
    func("asdfasdf");
}

如果直接编译的话会出现 no matching function for call to 'myclass::myclass(const char [9])' 的错误信息。
如果把函数参数改为 const string& 就可以编译通过。

技巧:重载函数

void func(string& ) { cout << "1" << endl; } // func函数1 
void func(const string& ) { cout << "2" << endl; }  // func函数2 

int main() {
	string s("abcd");
	func(s); //调用func函数1 
    func("asdfasdf"); //调用func函数2 
}

运行结果分别输出1,2
这样重载函数的好处是外部对象调用时不需要构造string对象,调用起来比较的方便。

如何理解

编写如下测试代码

class A{
public:
	A() { cout << "A()" << endl; }
	A(const char*) { cout << "A(const char*)" << endl; }
	A(A&) { cout << "A(A&)" << endl; }	
	
};

void func(A&) { cout << "call func(A&)" << endl; }

void func(const A&) { cout << "call func(const A&)" << endl;}

int main() {
	A a("abcdef"); // 调用A(const char*) 
	func(a); //调用func函数1 
	cout << endl;
    func("asdfasdf"); //调用func函数2 
}

运行结果如下
在这里插入图片描述
理解:
第一行输出A(const char*) 为A a(“abcdef”) 调用构造函数;
第二行输出call func(A&) 表示调用func过程没有任何拷贝过程;
第四行输出 A(const char*) 是关键点,代表这个字符串对象先调用A(const char*) 构造函数然后在把生成的对象作为const引用传递给参数。函数参数必须是const才能被接受,如果你在func函数里面需要进行非const的操作,则首先需要一个进行一个 const_cast<A&> 转型 (我只知道必须加const,不知道为什么要加const,有这方面详细的文档的哥们请留言)
简而言之:函数参数是const的引用具有调用构造函数复制新对象的能力(但不是一定会复制新对象)

对继承的影响

#include <iostream>

class Base {
public:
	//const Base&如果改为 Base& 编译将不通过 
    friend std::ostream&operator << (std::ostream& ,const Base&) { }
};

class A:public Base { };

int main() {
	std::cout << A(); // 调用Base的operator << 方法,需要对A对象转型,只能转为const Base& 
}

简而言之:加了const可以转为基类引用,而不需要复制新的对象

一个复杂的例子

这是我编写的一份关于继承和重载<< 的代码,代码虽然短,内容相当多,需要好好理解。

#include <iostream>
#include <string>

using namespace std;
 
class Base {
    string data;
public:
	virtual void setdata(string& data) { this->data = data; }
    virtual void setdata(const string& data){ this->data = data; }
    friend ostream&operator << (ostream& os,const Base& b) { // 如果把const删除则导致输出A对象失败,可以删除试下 
        os << b.data;
        return os;
    }
};

class A:public Base {
public:
    virtual void func() { }
    A() { }
    A(string& data) { setdata(data); }
    A(const char* data) { setdata(data); }
    A(const string& data) { setdata(const_cast<string&>(data)); } // 使用了const_cast 对const对象转型 
};

void func(const A& s) {
	cout << s << endl; // 匹配到 ostream&operator << (ostream& os,const Base& b); 函数 ;
}

int main() {
	cout << A("1234") << endl; //A("1234")调用了构造函数A(const string& data); 使用了上面的技巧
	func("5678"); // "5678"先调用A(const char*data) 构造,然后setdata(data)在调用 void setdata(const string& data) 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章