C++ 静态成员函数和lambda表达式的一些探索

7 篇文章 0 订阅
6 篇文章 0 订阅

故事的开始,从牛客网一道题目说起。

输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。
例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

题目怎么求解暂且不表,现在visual studio 2017中写好代码,如下:

bool mCmp(const string& s1, const string &s2) {
	return (s1 + s2) < (s2 + s1);
}

string PrintMinNumber(vector<int> numbers) {
	string result = "";
	vector<string> vecStr;
	for (int i : numbers)
	{
		vecStr.push_back(to_string(i));
	}
	sort(vecStr.begin(), vecStr.end(), mCmp);
	for (auto str : vecStr)
	{
		result += str;
	}
	return result;
}

int main()
{
	vector<int> numbers{ 6,1,23,45 };
	cout << PrintMinNumber(numbers) << endl;
	return 0;
}

自己测试的结果都是正确的。将上面的代码粘贴到牛客网OJ上。

很好,编译错误。

您的代码已保存
编译错误:您提交的代码无法完成编译点击对比用例标准输出与你的输出
In file included from a.cc:2:
./solution.h:14:36: error: reference to non-static member function must be called
sort(vecStr.begin(),vecStr.end(),mCmp);

这和我在VS里写的代码有什么区别呢?

仔细看,我在编译器里全局定义了函数,而在牛客网上,是写在一个类内的。由此引发了一些思考。

先看一下sort函数。

template <class RandomAccessIterator, class Compare>
  void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp)
comp: Binary function that accepts two elements in the range as arguments, 
and returns a value convertible to bool.
The value returned indicates whether the element passed
as first argument is considered to go before the second in the specific strict weak ordering it defines.
The function shall not modify any of its arguments.
This can either be a function pointer or a function object.

看解释的第一行,comp: Binary function that accepts two elements in the range as arguments, 比较函数应该是一个二元函数,意思就是括号里应该有且仅有两个参数。

emmm....我在类内写的mCmp不就是有两个参数吗?

由此,去问百度,查到了。

mCmp作为类内非静态成员函数,拥有一个隐式参数,实际上mCmp方法展开应该是这样的。

bool mCmp(Solution* tihis , const string& s1, const string &s2)

多了一个参数。this指针。学习到了。

又查到了一点。静态成员函数和非静态成员函数的根本区别在于有无this指针。

所以将上面的mCmp定义到类外或者加上static关键字就可以解决问题了。

结果:

-------------------------------------------------------------------------分割线---------------------------------------------------------------------------

从C#转过来,以前只是机械的记过,静态成员函数不能调用非静态成员,没想过为什么。这次彻底搞明白了。
类的静态成员在类加载的时候就已经分配内存,而此时类的非静态成员尚未分配内存,访问内存中不存在的东西自然会出错。

可以理解为类的静态成员是属于类的,非静态成员是属于对象的。类的函数哪里知道该用哪个对象的数据。

-------------------------------------------------------------------------分割线---------------------------------------------------------------------------

再看解释中的This can either be a function pointer or a function object.既然comp既可以是函数指针又可以是函数对象,那么我是不是可以使用lambda表达式去写呢?

class Solution {
public:
	static bool mCmp(const string& s1,const string &s2) {
		return (s1 + s2) < (s2 + s1);
	}

	string PrintMinNumber(vector<int> numbers) {
		string result="";
		vector<string> vecStr;
		for (int i:numbers)
		{
			vecStr.push_back(to_string(i));
		}
		sort(vecStr.begin(), vecStr.end(), 
            [](const string& s1, const string& s2) {return (s1 + s2) < (s2 + s1); });
		for (auto str:vecStr)
		{
			result += str;
		}
		return result;
	}
};

完美,运行通过,以前一直搞不清楚lambda表达式怎么使用,这次探索,恍然大悟,实在找不到比这个更合是的例子了。

C++ 11 中的 Lambda 表达式用于定义并创建匿名的函数对象,以简化编程工作。

至于什么[]如何捕获参数之类的,百度可以查到很详细的解释。

还可以这样使用:

	auto fun = [](const string& s1, const string& s2) {return (s1 + s2) < (s2 + s1); };
	sort(vecStr.begin(), vecStr.end(),fun);
function<bool(const string& s1, const string& s2)> fun= [](const string& s1, const string& s2) {return (s1 + s2) < (s2 + s1); };
	sort(vecStr.begin(), vecStr.end(),fun);

长见识了,但是还是用auto把....

--------------------------ps尊重知识产权的分割线----------------------------

有一些是从下面大佬的博客粘过来,

https://blog.csdn.net/u010982765/article/details/79021426

https://blog.csdn.net/Shrimp_millet/article/details/95040735

告辞。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值