@L B: I said I would replace the fixed-size array declaration with a new[] assignment declaration which would fix it(char* x=new[a.size()+1])
And, what do you mean by unnecessary copy of string parameter? it is a function parameter, at globalscope! there is no copy!
Instance has been constructed
Instance has been constructed
Copy has been constructed
Copy has been constructed
Assignment
Instance has been destructed
Assignment
Instance has been destructed
Instance has been destructed
Start of main
Do1:
Do2:
End of main
Instance has been destructed
Implementations use copy on write. As long as you don't modify the data you don't get copies, if you call functions that can change data you may get a deep copy.
Note: This is common practice in C++03 and the default behaviour in C++11
I don't see how this is all relevant. The OP was talking about creating his own string class, not using std::string. The behavior of std::string with regards to the code snippet Viliml posted isn't germane -- it didn't use std::string.
So after a lot of consfusion(mostly mine), I think we need to see what you've got for now about that class! Otherwise we can't know exatly how to do that!
struct TestClass
{
TestClass()
{
std::cout << "Instance of test has been constructed" << std::endl;
}
TestClass(const TestClass &from)
{
std::cout << "Copy of test has been constructed" << std::endl;
}
TestClass &operator=(const TestClass &from)
{
std::cout << "Test assignment" << std::endl;
return *this;
}
~TestClass()
{
std::cout << "Instance of test has been destructed" << std::endl;
}
};
struct weird_string
{
basic_string<TestClass> data;
weird_string()
{
cout << "Instance of string has been constructed" << endl;
}
weird_string(const weird_string &from)
{
cout << "Copy of string has been constructed" << endl;
}
weird_string(int n, TestClass d)
{
data=basic_string<TestClass>(n, d);
}
weird_string &operator=(const weird_string &from)
{
cout << "String assignment" << endl;
return *this;
}
~weird_string()
{
cout << "Instance of string has been destructed" << endl;
}
};
void Do1(weird_string t)
{
}
void Do2(weird_string &t)
{
}
int main()
{
weird_string test(1,TestClass());
cout << "Start of main" << endl;
std::cout << "Do1:" << endl;
Do1(test);
cout << "Do2:" << endl;
Do2(test);
cout << "End of main" << endl;
system ("pause");
return 0;
}
Instance of test has been constructed
Instance of test has been constructed
Copy of test has been constructed
Copy of test has been constructed
Copy of test has been constructed
Test assignment
Instance of test has been destructed
Test assignment
Instance of test has been destructed
Instance of test has been destructed
Instance of test has been destructed
Start of main
Do1:
Copy of string has been constructed
Instance of string has been destructed
Do2:
End of main
Instance of string has been destructed
Instance of test has been destructed
As you can see, there is copying in Do1, just like the first example with just TestClass.
I don't think Visual C++ uses COW strings. I have heard rumors that C++11 will force GCC to stop using COW strings but last I checked it was still used. To be safe it's better to pass by reference.
It certainly won't force anyone into any specific implementation. In most cases where COW resulted in better efficiency (cases where you couldn't avoid temporary objects) move semantics handles it very well, so maybe there isn't as much need for the overhead of a COW implementation as there was prior to C++11.
std::string wasn't strictly COW before C++11 in the first place, it was copy-on-non-const-member-function-call (e.g. non-const .begin())
Today, when it is an array and anyone can grab a reference (not a proxy object) to its element and access any other element of the same string through pointer arithmetics, now or later, it can only be copy-on-any-member-function-call, which is pretty much forbidding COW.