成员函数返回类成员变量的引用,有存在修改成员变量的值的风险。

很多时候我们将函数返回值设置为引用类型,这样可以提高函数返回的效率,而如果我们在类成员方法中这样做了,很可能会出一些问题。

参考如下代码:我们通过设置类成员方法 data() ,本意是想查看类私有变量的数值,为了提高效率我们增加了引用。

class Object {
private:
	int value;
public:
	Object(int x = 10) :value(x) {};
	int& data() { return value; }
};

int main()
{
	Object obj(10);
	obj.data() = 11;
	cout << "val : " << obj.data() << endl;
	return 0;
}

可以看到,我们使用obj.data() = 11;这条语句可以将obj对象的私有属性obj.value修改,这就造成了很大的安全隐患。

而我们即想要提高返回值效率,又不想变量在外部被修改,那么我们只需将返回值设置为常引用即可。

const int& data() { return value; }

这里的常引用指的是常量左值引用const Type&类型,而声明为常引用之后此函数的返回值就无法再修改我们的类私有成员属性了。
在这里插入图片描述

同理,在类成员函数后加const,也能有效的阻止成员函数自身修改类属性。原理是在类的成员方法中有个隐藏的this指针,它的类型是Object * const类型(这里限制了this不可改变指向)。

而我们添加了const参数后,它作用于此this指针后变成Object const * const类型(这里同时限制this不可改变指向,也不可修改所指向空间的数据) 。

因此,成员函数后声明为const后视为常方法,即函数内不可以对类成员属性做修改(同理也不可调用类的非常量方法,因为存在修改类成员属性的风险),但可以修改其他不通过this指针调用的变量,比如传入的形参。

参考以下示例:

class Object {
private:
	int value;
public:
	Object(int x = 10) :value(x) {};
	const int& data() { return value; }
	void show()
	{
		cout << typeid(this).name() << endl;
	}
	void show() const
	{
		cout << typeid(this).name() << endl;
	}
};

int main()
{
	Object obj(10);
	obj.show();		// 普通对象调用普通方法

	const Object Cobj(10);
	Cobj.show();	// 常对象调用常方法
	
	return 0;
}

在这里插入图片描述
注:Object * const this 修饰的是this所指向之值不可被修改,对指针自身并没有限定,因此我们使用typeid 输出this的类型时为 Object * 类型,具体const修饰指针案例请参考下面给出的整理:

const 对指针修饰时的情况及含义(const 在*左边,则修饰的是“p”,const 在右边,修饰的是p)

  • const int * p <=等价=> int const *p :指针p所指的内存单元为常量,不可修改该内存
  • int * const p:指针p自己是常量,该指针的地址值不可修改。const int *p = new int(); 这里的 p 被const限定
  • const int * const p :以上两种情况都包含:既不可修改指针值也不可修改指针所指位置的值。

声明为的成员函数 const 不能更改成员数据-在此类函数中, this 指针是指向 const 对象的指针。
——参考自《https://docs.microsoft.com/zh-cn/cpp/cpp/this-pointer?view=msvc-160

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
静态成员函数无法直接访问非静态成员变量,因为非静态成员变量是属于具体的对象的,而静态成员函数是属于整个的。如果想在静态成员函数中调用非静态成员函数并且不改变原成员变量,可以将非静态成员函数声明为const成员函数。 对于const成员函数,它保证不会修改的任何非静态成员变量,因此可以在静态成员函数中调用它,而不会改变原成员变量。 下面是一个示例代码: ``` class MyClass { private: int m_value; public: MyClass(int value) : m_value(value) {} int getValue() const { return m_value; } static int staticFunc(const MyClass& obj) { return obj.getValue() + 1; } }; int main() { MyClass obj(10); std::cout << MyClass::staticFunc(obj) << std::endl; // 输出11 return 0; } ``` 在上面的代码中,MyClass中定义了一个非静态成员函数getValue和一个静态成员函数staticFunc。getValue被声明为const成员函数,保证不会修改m_value成员变量。在staticFunc中,传入一个MyClass型的引用,调用其getValue函数并加1,返回结果。 在main函数中,定义一个MyClass对象obj,并将它传入staticFunc函数中调用,最后输出结果11。 需要注意的是,如果非静态成员函数需要修改成员变量,就不能声明为const成员函数了。此时,可以考虑将需要修改成员变量声明为mutable,表示即使在const成员函数中也可以修改它的。不过,修改mutable成员变量的行为需要谨慎,要确保不会破坏的不变量。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我叫RT

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值