是否可以在 C++ 中对 return 进行交换,而不是按值对 return 进行交换?
Is it possible to do a swap on return in c++, instead of return by value?
假设我正在用 C++ 编写字符串 class(我知道我可以使用该库)。字符串长度是可变的,存储 space 在构造函数中动态分配并在析构函数中释放。当main
函数调用c=a+b
时(a,b,c
是字符串),operator+
成员函数会创建一个临时对象,用于存储拼接后的字符串a+b
,returns到main
函数,然后调用operator=
成员函数,释放c
中原来存放的字符串,将临时字符串a+b
中的数据复制到c
,最后临时a+b
被销毁
我想知道是否有办法做到这一点:我希望它交换数据指针,而不是让 operator=
将数据从 a+b
复制到 c
a+b
和 c
,这样当 a+b
被破坏时,它会破坏 c
中的原始数据(这就是我们想要的),而 c
现在无需复制即可获取 a+b
的结果。
我知道编写一个 2 参数成员函数 setToStrcat
并调用 c.setToStrcat(a,b)
可以做到这一点。例如,函数可以编码为:
void String::setToStrcat(const String& a,const String& b){
String tmp(a.len+b.len); int i,j;
for(i=0;i<a.len;i++) tmp[i]=a[i];
for(j=0;j<b.len;i++,j++) tmp[i]=b[j];
tmp[i]='[=12=]'; this->swap(tmp);
}
void String::swap(String& a){
int n=len; len=a.len; a.len=n;
char *s=str; str=a.str; a.str=s;
}
我省略了我的构造函数(分配 len+1
字符类型 spaces)和 operator[]
(returns 对 i
第一个字符)。 swap
函数交换了*this
和tmp
之间的数据指针和长度变量,这样当交换后tmp
被析构的时候,实际上是原来存储在[中的数据=39=](main
函数中的String c
)被破坏。 *this
现在拥有的 (c.str
) 是连接的字符串 a+b
.
我想知道是否有办法将c=a+b
的性能优化到同样的水平。我尝试 c.swap(a+b)
并将 a+b
的 return 类型更改为 String&
,但我收到警告(引用局部变量)并且 GDB 显示临时文件在发生交换,而我想要另一种方式。
我觉得我的问题很笼统。在 C++ 编程中,我们经常需要一个临时对象来存储函数的结果,但是当我们在 main 函数中将其分配给另一个对象时,我们是否可以不复制数据而是使用(更快的)指针交换来代替?实现这一目标的巧妙方法是什么?
在 C++11 中,您可以通过编写移动构造函数来完成此操作。右值引用被添加到语言中以解决这个确切的问题。
class String {
...
String(String&& s) : str(nullptr) {
this->swap(s);
}
String& operator=(String&& s) {
this->swap(s);
}
...
String operator+(String const& other) {
// (your implementation of concatenation here)
}
...
}
那么像这样的代码将不会触发额外的复制构造函数或内存分配,它只会将分配的内存从临时对象(从 operator+ 返回的东西)移动到新对象 c
.
String c = a + b;
假设我正在用 C++ 编写字符串 class(我知道我可以使用该库)。字符串长度是可变的,存储 space 在构造函数中动态分配并在析构函数中释放。当main
函数调用c=a+b
时(a,b,c
是字符串),operator+
成员函数会创建一个临时对象,用于存储拼接后的字符串a+b
,returns到main
函数,然后调用operator=
成员函数,释放c
中原来存放的字符串,将临时字符串a+b
中的数据复制到c
,最后临时a+b
被销毁
我想知道是否有办法做到这一点:我希望它交换数据指针,而不是让 operator=
将数据从 a+b
复制到 c
a+b
和 c
,这样当 a+b
被破坏时,它会破坏 c
中的原始数据(这就是我们想要的),而 c
现在无需复制即可获取 a+b
的结果。
我知道编写一个 2 参数成员函数 setToStrcat
并调用 c.setToStrcat(a,b)
可以做到这一点。例如,函数可以编码为:
void String::setToStrcat(const String& a,const String& b){
String tmp(a.len+b.len); int i,j;
for(i=0;i<a.len;i++) tmp[i]=a[i];
for(j=0;j<b.len;i++,j++) tmp[i]=b[j];
tmp[i]='[=12=]'; this->swap(tmp);
}
void String::swap(String& a){
int n=len; len=a.len; a.len=n;
char *s=str; str=a.str; a.str=s;
}
我省略了我的构造函数(分配 len+1
字符类型 spaces)和 operator[]
(returns 对 i
第一个字符)。 swap
函数交换了*this
和tmp
之间的数据指针和长度变量,这样当交换后tmp
被析构的时候,实际上是原来存储在[中的数据=39=](main
函数中的String c
)被破坏。 *this
现在拥有的 (c.str
) 是连接的字符串 a+b
.
我想知道是否有办法将c=a+b
的性能优化到同样的水平。我尝试 c.swap(a+b)
并将 a+b
的 return 类型更改为 String&
,但我收到警告(引用局部变量)并且 GDB 显示临时文件在发生交换,而我想要另一种方式。
我觉得我的问题很笼统。在 C++ 编程中,我们经常需要一个临时对象来存储函数的结果,但是当我们在 main 函数中将其分配给另一个对象时,我们是否可以不复制数据而是使用(更快的)指针交换来代替?实现这一目标的巧妙方法是什么?
在 C++11 中,您可以通过编写移动构造函数来完成此操作。右值引用被添加到语言中以解决这个确切的问题。
class String {
...
String(String&& s) : str(nullptr) {
this->swap(s);
}
String& operator=(String&& s) {
this->swap(s);
}
...
String operator+(String const& other) {
// (your implementation of concatenation here)
}
...
}
那么像这样的代码将不会触发额外的复制构造函数或内存分配,它只会将分配的内存从临时对象(从 operator+ 返回的东西)移动到新对象 c
.
String c = a + b;