考虑如下代码:
void myfunc(string str)
{
// delete pointer str is NOT necessary
{
}
string a;
void myfunc(shared_ptr<string> str)
{
void myfunc(shared_ptr<string> str)
{
void myfunc(MyString str)
显然,这个函数需要传入一个字符串参数。因此下面是调用此函数的方法。
myfunc("abc");
但是,如果我们要传入一个NULL呢?
myfunc(NULL);
砰!程序出错了!C++的basic_string的构造函数不允许NULL值。
当然,我们可以传入一个空字符串。
myfunc("");
或者,传入一个空字符串对象。
myfunc(a);
但这些都不是以NULL值作参数来传递。
既然可以变通,为何一定要传入NULL值呢?设有一个规范。
void createBook(string title);
规范要求,title是一个字符串,可以为null.
规范设计者显然是使用Java语言的,因此使用Java语言可以安全地传入null值。
但若用C++语言来实现此规范,就遇到上面的问题了。即使像上面一样传入空字符串,它也不是NULL值。规范要求,必须允许传入NULL值。
使用C++11的shared_ptr<string>,可以解决此问题。
{
}
myfunc(NULL);
但是,新问题来了,
myfunc("abc"); // error: No matching function for call to 'myfunc'
对于类型是shared_ptr<string>的参数,必须使用make_shared<string>()生成shared_ptr<string>后再传入。于是有了下面的代码:
myfunc(make_shared<string>("abc"));
下面是目前为止,行之有效的代码:
{
}
myfunc(NULL);
myfunc(make_shared<string>("abc"));
每次都要输入shared_ptr<string>,或make_shared<string>,不够简短。下面来简化代码的输入。
第一,由于shared_ptr<string>是类型,可以使用typedef来简化它。
typedef shared_ptr<string> MyString;
{
shared_ptr<string> MMS(string str)
{
return make_shared<string>(str);
void myfunc(MyString str)
myfunc(NULL);
void myfunc(shared_ptr<string> str)
{
// use pointer str
}
第二,make_shared<string>是一个模板方法,可以通过引入一个名称较短的函数来替换它。
{
return make_shared<string>(str);
}
myfunc(MMS("abc"));
MMS表示Make MyString的意思。但是,增加的函数调用也同时增加了程序的负担。另一方法是使用#define来定义一个宏。
#define MMS(...) make_shared<string>(__VA_ARGS__)
myfunc(MMS("abc"));
省略号...表示__VA_ARGS__所传入的参数是字符串。因此,完全适合这里的需要。下面是实现后的全部代码。
#define MMS(...) make_shared<string>(__VA_ARGS__)
typedef shared_ptr<string> MyString;
{
}
myfunc(nullptr);
myfunc(MMS("abc"));
代码简短了许多,最主要的,它支持了将NULL值传入给字符串形参。
此外,使用shared_ptr<string>还有一个好处,就是不需要显式地手工清理内存。
{
// use pointer str
cout << str->length() << endl;
// delete pointer str is NOT necessary
} // pointer str will be deleted automatically here