conversion from string to char*

Pages: 12
@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!
Last edited on
viliml wrote:
there is no copy!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <iostream>

struct TestClass
{
    TestClass()
    {
        std::cout << "Instance has been constructed" << std::endl;
    }
    TestClass(const TestClass &from)
    {
        std::cout << "Copy has been constructed" << std::endl;
    }
    TestClass &operator=(const TestClass &from)
    {
        std::cout << "Assignment" << std::endl;
    }
    ~TestClass()
    {
        std::cout << "Instance has been destructed" << std::endl;
    }
};

void Do1(TestClass t)
{
}
void Do2(TestClass &t)
{
}

int main()
{
    std::cout << "Start of main" << std::endl;
    TestClass test;
    std::cout << "Do1:" << std::endl;
    Do1(test);
    std::cout << "Do2:" << std::endl;
    Do2(test);
    std::cout << "End of main" << std::endl;
}
Start of main
Instance has been constructed
Do1:
Copy has been constructed
Instance has been destructed
Do2:
End of main
Instance has been destructed
http://ideone.com/BNxzL
Last edited on
OK, so I replace "string a" with "string& a", in smaller programs, it's no big deal!
Never start bad habits ;)
Bad habit?
http://ideone.com/KHLVh

No deep copying there ;^)
Last edited on
You can't make std::string(const string&) print out to see that it makes a copy, even if it doesn't actually do a deep copy.
I've edited your code,
no function call is forcing copy constructors (for elements of the string):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include <iostream>
#include <string>
 
struct TestClass
{
    TestClass()
    {
        std::cout << "Instance has been constructed" << std::endl;
    }
    TestClass(const TestClass &from)
    {
        std::cout << "Copy has been constructed" << std::endl;
    }
    TestClass &operator=(const TestClass &from)
    {
        std::cout << "Assignment" << std::endl;
        return *this;
    }
    ~TestClass()
    {
        std::cout << "Instance has been destructed" << std::endl;
    }
};
 
typedef std::basic_string<TestClass> weird_string;
 
void Do1(weird_string t)
{
}
void Do2(weird_string &t)
{
}
 
int main()
{
    weird_string test(1,TestClass());
    std::cout << "Start of main" << std::endl;
    std::cout << "Do1:" << std::endl;
    Do1(test);
    std::cout << "Do2:" << std::endl;
    Do2(test);
    std::cout << "End of main" << std::endl;
}
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
Last edited on
Optimizations off? What if in Do1 you change one of the TestClasses in t with the subscript[] operator?
@bazzy: there is indeed deep copying, but it happens on weird_string, not TestClass! That is why it doesn't print anything!
If so, then modifying t[0] would modify test[0] in main!
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
Thanks, useful to know. But still bad habit for other classes that don't do that same thing.
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.



OOOOOOOOOOOOOh! All this time I didnt notice that you make YOUR OWN string class! You alway said "string" so there was a misunderstanding, sorry!
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!
Oh, and I know this is now off-topic, but Bazzy, I've made a more complicated version of your code to prove there is indeed copying in that code too!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
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.
With copy on write you do get a copy of the container but not a copy of the elements.
If you are interested in the details, we can start a new thread
Last edited on
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.
Last edited on
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.
Last edited on
Topic archived. No new replies allowed.
Pages: 12