String type allowed in copy constructor?

I am using an example from Sams Teach Yourself C++ In One Hour a day. I pretty much understand concepts relating to the copy constructor. A couple of things that I can use a hand on are;
Why can I put just a string in the
 
UseMyString("string");

an instance of a MyString object is called sayHello is legal
 
UseMyString(sayHello);

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
68
69
70
71
72
73
74
75
76
77
#include <iostream>
#include <string.h>
using namespace std;

class MyString
{
private:
	char* buffer;

public:

	MyString(const char* initString) // constructor
	{
		buffer = NULL;
		cout << "Default constructor: creating new MyString" << endl;
		if (initString != NULL)
		{
			buffer = new char[strlen(initString) + 1];
			strcpy(buffer, initString);

			cout << "buffer points to: 0x" << hex;
			cout << (unsigned int*)buffer << endl;
		}
	}

	MyString(const MyString& copySource) // Copy constructor
	{
		buffer = NULL;
		cout << "Copy constructor: copying from MyString" << endl;
		if (copySource.buffer != NULL)
		{
			// allocate own buffer 
			buffer = new char[strlen(copySource.buffer) + 1];

			// deep copy from the source into local buffer
			strcpy(buffer, copySource.buffer);

			cout << "buffer points to: 0x" << hex;
			cout << (unsigned int*)buffer << endl;
		}
	}

	// Destructor
	~MyString()
	{
		cout << "Invoking destructor, clearing up" << endl;
		delete[] buffer;
	}

	int GetLength()
	{
		return strlen(buffer);
	}

	const char* GetString()
	{
		return buffer;
	}
};

void UseMyString(MyString str)
{
	cout << "String buffer in MyString is " << str.GetLength();
	cout << " characters long" << endl;

	cout << "buffer contains: " << str.GetString() << endl;
	return;
}

int main()
{
	MyString sayHello("Hello from String Class");
	UseMyString(sayHello);
        //UseMyString("string"); this is not required type but it still compiles

	return 0;
}
Last edited on
Because C++ will implicitly convert the const char* into a MyString.

To prevent this confusion, mark your MyString constructor as explicit.
explicit MyString(const char* initString) { /* ... */ }

Further reading:
https://softwareengineering.stackexchange.com/questions/190716/is-relying-on-implicit-argument-conversion-considered-dangerous
https://blogs.msdn.microsoft.com/oldnewthing/20060524-12/?p=31083
Last edited on
Unless you make a constructor "explicit" it acts as a conversion function. So UseMyString("hello") first calls the MyString ctor that takes a string literal, creates a MyString object, and passes it to UseMyString. If you put the keyword "explicit" in front of the first MyString ctor then it won't be used implicitly like that.
OK @Ganado, @tpb I see. I am learning about the keyword explicit. This helps so much Thanks
Topic archived. No new replies allowed.