比较返回一个对象,到底该怎么写?
// 类型一
std::string getTimeNowString()
{
string str = "2010-05-04";
return str;
}
// 类型二
std::string getTimeNowString()
{
string str = "2010-05-04";
return std::move(str);
}
// 类型三
std::string& getTimeNowString()
{
string str = "2010-05-04";
return std::move(str);
}
// 类型四:运行期崩溃
std::string&& getTimeNowString()
{
string str = "2010-05-04";
return std::move(str);
}
答案是:使用类型一即可,因为
在c++11以后,编译器自动执行了优化,只要该类型有移动构造函数即可保证效率。参见:
我们来测试一下效果是否一样,我们自己写一个类:
#define PRINT(a) cout << "行" << __LINE__ << "调用:"; a
class Base
{
public:
int a;
char * buf = NULL;
void SetStr(const char * buffer)
{
if (!buffer)
return;
if (buf)
delete[] buf;
buf = new char[strlen(buffer) + 1];
strcpy(buf, buffer);
}
public:
Base() : a(1)
{
cout << "构造0-行" << __LINE__ << "\n";
}
Base(int i) : a(i)
{
cout << "构造1-行" << __LINE__ << "\n";
}
virtual ~Base()
{
cout << "析构\n";
if (buf)
delete[] buf;
}
public:
Base(const Base& other) : a(other.a)
{
SetStr(other.buf);
cout << "拷贝构造-行" << __LINE__ << "\n";
}
Base & operator=(const Base& other) {
this->a = other.a;
SetStr(other.buf);
cout << "拷贝赋值-行" << __LINE__ << "\n";
return *this;
}
Base(Base&& other) // 这里不能是const类型,因为可能要更改other,
{
this->a = other.a;
this->buf = other.buf;
other.buf = NULL; // 交接堆数据空间
cout << "转移构造-行" << __LINE__ << "\n";
}
Base & operator=(Base&& other) {
this->a = other.a;
this->buf = other.buf;
other.buf = NULL; // 交接堆数据空间
cout << "转移赋值-行" << __LINE__ << "\n";
return *this;
}
public:
int getInt()
{
return a;
}
int && getRvalueInt()
{
// notice that it's fine to move a primitive type--remember, std::move is just a cast
return std::move(a);
}
};
类型一测试:
// 测试返回值问题
Base testReturn()
{
Base base(1);
base.SetStr("hello, world");
cout << "__________" << endl;
return base;
}
int main()
{
Base base1 = testReturn1();
return 0;
}
输出:
构造1-行48
__________
转移构造-行76
析构
析构
类型二测试:
// 返回前调用std::move()
Base testReturn2()
{
Base base(1);
base.SetStr("hello, world");
cout << "__________" << endl;
return std::move(base);
}
输出结果与之前的结果一模一样;
经过测试,动态数组也是一样的,不需要特别的写法;
std::vector<Base> vec;
return vec;