C
Christian Meier
Hi NG
A few days ago there was a thread in comp.lang.c++.moderated with the
subject "Return versus Side-Effect". The OP asked whether to use "return by
value" or an additional parameter of type "C&" which will be overwritten
with a result.
The most posters advised the OP to use the version with the return value. No
only for aesthetic reasons but also for performance reasons because of the
return value optimization.
I wrote a little sample program to test their assertion.
For aesthetic reasons I prefer the "return by value" version. But I found
out that for performance reasons both versions are necessary. It depends on
how you call the function. Sometimes the "return by value" is faster than
the "out-parameter" version and sometimes the other way around. Can you
confirm my conclusion?
Best regards,
Chris
Here is my test code:
#include <iostream>
using std::cout;
#include <iostream>
using std::cout;
class MyString
{
public:
MyString() : value(NULL) { cout << "ctor 0\n"; }
MyString(const char*);
MyString(const MyString&);
~MyString() { delete[] value; }
MyString& operator=(const char* newValue);
MyString& operator=(const MyString&);
private:
char* value;
};
MyString::MyString(const char* newValue)
{
cout << "ctor 1\n";
if (newValue == NULL) {
value = NULL;
} else {
int length = strlen(newValue);
value = new char[length + 1];
strcpy(value, newValue);
}
}
MyString::MyString(const MyString& other)
{
cout << "copy ctor\n";
if (other.value == NULL) {
value = NULL;
} else {
int length = strlen(other.value);
value = new char[length + 1];
strcpy(value, other.value);
}
}
MyString& MyString:perator=(const char* newValue)
{
cout << "op =0\n";
if (value != NULL) {
delete[] value;
} // if
if (newValue == NULL) {
value = NULL;
} else {
int length = strlen(newValue);
value = new char[length + 1];
strcpy(value, newValue);
}
return *this;
}
MyString& MyString:perator=(const MyString& other)
{
cout << "op =1\n";
if (this == &other) {
return *this;
} // if
if (value != NULL) {
delete[] value;
} // if
if (other.value == NULL) {
value = NULL;
} else {
int length = strlen(other.value);
value = new char[length + 1];
strcpy(value, other.value);
}
return *this;
}
MyString returnByVal()
{
MyString ret("return value");
return ret;
}
void returnByParam(MyString& out)
{
out = "return value";
}
int main()
{
// First test case where the out parameter is faster.
cout << "Before returnByVal()\n";
MyString str1;
str1 = returnByVal();
cout << "\nBefore returnByParam()\n";
MyString str2;
returnByParam(str2);
cout << "Finished test 1\n\n\n";
// Second test case where return by value is faster.
cout << "Before returnByVal()\n";
MyString str3 = returnByVal();
cout << "\nBefore returnByParam()\n";
MyString str4;
returnByParam(str4);
cout << "Finished test 2\n";
}
The output is the following:
Before returnByVal()
ctor 0
ctor 1
op =1
Before returnByParam()
ctor 0
op =0
Finished test 1
Before returnByVal()
ctor 1
Before returnByParam()
ctor 0
op =0
Finished test 2
In the first test case the "out-parameter" version is faster.
In the second test case the "return by value" version is faster.
A few days ago there was a thread in comp.lang.c++.moderated with the
subject "Return versus Side-Effect". The OP asked whether to use "return by
value" or an additional parameter of type "C&" which will be overwritten
with a result.
The most posters advised the OP to use the version with the return value. No
only for aesthetic reasons but also for performance reasons because of the
return value optimization.
I wrote a little sample program to test their assertion.
For aesthetic reasons I prefer the "return by value" version. But I found
out that for performance reasons both versions are necessary. It depends on
how you call the function. Sometimes the "return by value" is faster than
the "out-parameter" version and sometimes the other way around. Can you
confirm my conclusion?
Best regards,
Chris
Here is my test code:
#include <iostream>
using std::cout;
#include <iostream>
using std::cout;
class MyString
{
public:
MyString() : value(NULL) { cout << "ctor 0\n"; }
MyString(const char*);
MyString(const MyString&);
~MyString() { delete[] value; }
MyString& operator=(const char* newValue);
MyString& operator=(const MyString&);
private:
char* value;
};
MyString::MyString(const char* newValue)
{
cout << "ctor 1\n";
if (newValue == NULL) {
value = NULL;
} else {
int length = strlen(newValue);
value = new char[length + 1];
strcpy(value, newValue);
}
}
MyString::MyString(const MyString& other)
{
cout << "copy ctor\n";
if (other.value == NULL) {
value = NULL;
} else {
int length = strlen(other.value);
value = new char[length + 1];
strcpy(value, other.value);
}
}
MyString& MyString:perator=(const char* newValue)
{
cout << "op =0\n";
if (value != NULL) {
delete[] value;
} // if
if (newValue == NULL) {
value = NULL;
} else {
int length = strlen(newValue);
value = new char[length + 1];
strcpy(value, newValue);
}
return *this;
}
MyString& MyString:perator=(const MyString& other)
{
cout << "op =1\n";
if (this == &other) {
return *this;
} // if
if (value != NULL) {
delete[] value;
} // if
if (other.value == NULL) {
value = NULL;
} else {
int length = strlen(other.value);
value = new char[length + 1];
strcpy(value, other.value);
}
return *this;
}
MyString returnByVal()
{
MyString ret("return value");
return ret;
}
void returnByParam(MyString& out)
{
out = "return value";
}
int main()
{
// First test case where the out parameter is faster.
cout << "Before returnByVal()\n";
MyString str1;
str1 = returnByVal();
cout << "\nBefore returnByParam()\n";
MyString str2;
returnByParam(str2);
cout << "Finished test 1\n\n\n";
// Second test case where return by value is faster.
cout << "Before returnByVal()\n";
MyString str3 = returnByVal();
cout << "\nBefore returnByParam()\n";
MyString str4;
returnByParam(str4);
cout << "Finished test 2\n";
}
The output is the following:
Before returnByVal()
ctor 0
ctor 1
op =1
Before returnByParam()
ctor 0
op =0
Finished test 1
Before returnByVal()
ctor 1
Before returnByParam()
ctor 0
op =0
Finished test 2
In the first test case the "out-parameter" version is faster.
In the second test case the "return by value" version is faster.