Reputation: 973
Suppose I'm coding a string class in C++ (I know I can use the library). The string length is variable and the storage space is dynamically allocated in the constructor and freed in the destructor. When the main
function calls c=a+b
(a,b,c
are strings), the operator+
member function creates a temporary object that stores the concatenated string a+b
, returns it to the main
function, and then the operator=
member function is called to free the string originally stored in c
and copy data from the temporary string a+b
to c
, and finally the temporary a+b
is destructed.
I'm wondering if there's a way to make this happen: instead of having the operator=
copy data from a+b
to c
, I want it to swap the data pointers of a+b
and c
, so that when a+b
is destructed, it destructs the original data in c
(which is what we want), while c
now takes the result of a+b
without needing to copy.
I know coding a 2-parameter member function setToStrcat
and calling c.setToStrcat(a,b)
can do this. For example, the function can be coded as:
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]='\0'; 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;
}
I omitted the definitions of my constructor (which allocates len+1
char-type spaces) and operator[]
(which returns a reference of the i
th character). The swap
function swaps the data pointers and length variables between *this
and tmp
, so that when tmp
is destructed after the swap, it is actually the data originally stored in *this
(the String c
in the main
function) that is destructed. What *this
now has in its possession (c.str
) is the concatenated string a+b
.
I would like to know if there is a way to optimize the performance of c=a+b
to the same level. I tried c.swap(a+b)
and changed the return type of a+b
to String&
, but I receive warning (reference to a local variable) and GDB shows that the temporary gets destructed before the swap happens, while I want the other way.
I think my question is general. In C++ programming, we often need a temporary object to store the result of a function, but when we assign it to another object in the main function, can we not copy the data but use a (much faster) swap of pointers instead? What is a neat way of making this happen?
Upvotes: 4
Views: 747
Reputation: 4325
In C++11, you can do this by writing a move constructor. Rvalue references were added to the language to solve this exact problem.
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)
}
...
}
Then code like this will not trigger an extra copy constructor or a memory allocation, it will just move the allocated memory from the temporary (the thing returned from operator+) to the new object c
.
String c = a + b;
Upvotes: 1