Exploring Constructors with C-String and New Char[]

  • Thread starter yungman
  • Start date
In summary: Thanks,In summary, the Constructors in this code are confusing and I still don't understand them. The Copy Constructor in line 17 uses new memory, which is extra work.
  • #1
yungman
5,718
241
I am still trying to study more on the Constructors. This is the program that can copy c-string into an Object member data.

I redo the program. I separate both Constructor into Separate Classes to eliminate all the confusions:
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;
class vecC {
public:
    char name[Nsize];
    vecC(const char* desc)
    {   strncpy_s(name, Nsize, desc, Nsize);
        cout << "[Con1] for Cname: " << (*this).name << "\n\n";
    }
    void print() {  cout << name << "\n\n"; }
};
class vecP {
public:
    char*name;
    vecP(const char* n)//Need to add const to use "Ptname" in main()
    {   name = new char[Nsize];
        strncpy_s(name, Nsize, n, Nsize);
        cout << "[Con2] for name: " << (*this).name << "\n\n";
    }
    void print() { cout << (*this).name << "\n\n"; }
};
int main()
{
    vecC CstrName("Cname");
    vecP PtrName("Ptname");
    vecC CopyCstr = CstrName;
    vecP CopyPtr = PtrName;
    CopyCstr.print();
    CopyPtr.print();
    return 0;
}

Constructors in line 8 and line 17 do the same thing, but the one in line 17 use new char[] where as in line 8 uses just a c-string and copy it in. The book tends to use the one in line 17. Not only I have to have extra step to create new memory, I have to have Destructor to delete the new memory. What is the advantage of line 17?

Thanks
 
Last edited:
Technology news on Phys.org
  • #2
The two constructors are not doing the same thing, despite the title of this thread. The constructor with a parameter of type const char* is used when you call the constructor with a string literal; e.g., as in this line:
vec3 CstrName("Cname");

The other constructor with a char* parameter is used when you call the constructor with a char array; e.g., as in these lines:
char Ar[Nsize] = "Ptname";
vec3 PtrName(Ar);

BTW, the word is destructor, which is linguistically related to destroy. Distructor is not a word in English.
 
  • Like
Likes Jarvis323, sysprog, Vanadium 50 and 1 other person
  • #3
Mark44 said:
The two constructors are not doing the same thing, despite the title of this thread. The constructor with a parameter of type const char* is used when you call the constructor with a string literal; e.g., as in this line:
vec3 CstrName("Cname");

The other constructor with a char* parameter is used when you call the constructor with a char array; e.g., as in these lines:
char Ar[Nsize] = "Ptname";
vec3 PtrName(Ar);

BTW, the word is destructor, which is linguistically related to destroy. Distructor is not a word in English.
Thanks Mark,

But I put it on the note that I could have remove the const on the second and use string literal to do the same as the first one. The reason I did not do that is because if I put const on the second constructor, it becomes exactly the same as the first one and compiler won't know which one to use. VS flag me error to do that. That's the only reason I remove the const on the second one so people can actually copy into the IDE and run to see the result.

I am more interested in what is the advantage and disadvantage of one just straight copy and the second one create New memory. The book always use New memory that needs more lines of code.

ThanksThis Constructor and Copy Constructor are very confusing to me, it's as bad as pointers those days. When to use const, when to use New memory and all these. I still get tripped by these if I am not careful. I have been reading both chapters on Classes over one more time to try to find out what I missed. All the overloading seems to be more straight forward. After stepping through two or three programs to see how the compiler works, still I am not comfortable with the Constructors.
 
Last edited:
  • #4
When you allocate the memory using new, you can choose the size to accommodate the C-string that is being passed to the constructor. You don't do this. In the second contructor you use a fixed size Nsize.

How about instead, you do something like Pname = new char[strlen(n)+1];? (I think you need to add 1 for the null byte at the end of a C-string, but I'm not sure of this because I never use C-strings myself, but only std::string)

[added: it appears that what I wrote is probably correct because strlen() returns the number of actual text characters, not including the terminating null byte, see e.g. here.]
 
Last edited:
  • Like
Likes Jarvis323 and yungman
  • #5
jtbell said:
When you allocate the memory using new, you can choose the size to accommodate the C-string that is being passed to the constructor. You don't do this. In the second contructor you use a fixed size Nsize.

How about instead, you do something like Pname = new char[strlen(n)+1];? (I think you need to add 1 for the null byte at the end of a C-string, but I'm not sure of this because I never use C-strings myself, but only std::string)

[added: it appears that what I wrote is probably correct because strlen() returns the number of actual text characters, not including the terminating null byte, see e.g. here.]
Thanks

Yes, I know that, it's shorter to write to show the program to ask question. Also, if I have an array of structures, I want to keep the sizes the same for all the elements in the array, I need to keep all of them the same size Nsize.

So there is no advantage of using New memory?

Thanks
 
  • #6
Hi Guys, I changed the program in the post#1. I use two classes, one for the Constructor using copying c-string, the other using New memory. Now both passing string literal, so the process is identical.

I want to double check the DEEP COPY ability. Both seems to be DEEP COPYING as you can see in line 28 and line 29 I did a copy over using default Copy Constructor in the complier and display the name out. Both are correct. This is the question I am looking for answers.

I don't see any difference using either one of them.
 
  • #7
yungman said:
Also, if I have an array of structures, I want to keep the sizes the same for all the elements in the array, I need to keep all of them the same size Nsize.

So there is no advantage of using New memory?
Correct. If the char arrays in each structure must all be the same size, I see no advantage to allocating them dynamically using new.
 
  • Like
Likes Jarvis323 and yungman
  • #8
I made an illustration to try and show the difference.

arr.png


This difference will become important when you try to write and read them from disk.
 
  • Like
Likes yungman and sysprog
  • #9
Jarvis323 said:
I made an illustration to try and show the difference.

View attachment 275052

This difference will become important when you try to write and read them from disk.
Thanks Jarvis323. Merry Christmas

I have been working on this the whole day, almost forgot it's Christmas Eve! Our party is tomorrow, today is just another day, all 3 of us just doing our own thing!

While I was waiting for the reply, I actually modified the program to show the address of all 4 Objects to proof they have different address just like what you drew:
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;
class vecC {
public:
    char name[Nsize];
    vecC(const char* desc)
    {   strncpy_s(name, Nsize, desc, Nsize);
        cout << "[Con1] for name:  " << (*this).name <<
            ", address: this=" << this << "\n\n";
    }
    void print() {  cout << " CopyCstr name:   " << name <<
        ", address: this=" << this << "\n\n"; }
};
class vecP {
public:
    char*name;
    vecP(const char* n)
    {   name = new char[Nsize];
        strncpy_s(name, Nsize, n, Nsize);
        cout << "[Con2] for name: " << (*this).name <<
            ", address: this=" << this << "\n\n";
    }
    void print() { cout << " CopyPtr name:   " << (*this).name <<
        ", address: this=" << this << "\n\n"; }
};
int main()
{
    vecC CstrName("Cname");
    vecC CopyCstr = CstrName;
    CopyCstr.print();
    vecP PtrName("Ptname");
    vecP CopyPtr = PtrName;
    CopyPtr.print();
    return 0;
}
This is the printout:
Constructor compare.jpg


You can see the address of the objects are all different, so they are DEEP COPY in both cases.

Thanks you so much. Merry Christ
Now I am going to start working on Copy Constructor! These Constructors are as hard if not harder than pointers so far. I have been kind of stumbling around long enough, I just determine to work through this instead of rushing to the last chapter. If I can't get to the last chapter of the book this year, so be it. This is important. Where to put the const, how the compiler steps...
 
Last edited:
  • Like
Likes Jarvis323
  • #10
I found the difference between the two. In this situation, using pointer char*name FAILED.
the reason is when using pointer, copying using CopyPtr = PtrName ONLY copied the address name. So when I change the name of PtrName from "PtName" to "delete", it change the name in CopyPtr to "delete".

This is the final program that show this:
C++:
[/SIZE]
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;
class vecC {
public:
    char name[Nsize];
    vecC(const char* desc)
    {   strncpy_s(name, Nsize, desc, Nsize);
        cout << "[Con 1] for name:          " << (*this).name <<
            ", address: this=" << this << "\n\n";
    }
    void print() {  cout << " [print], CopyCstr name:   " << name <<
        ", address: this=" << this << "\n\n"; }
    void setName(const char* setC) { strncpy_s(name, Nsize, setC, Nsize); }
};
class vecP {
public:
    char*name;
    vecP(const char* n)
    {   name = new char[Nsize];
        strncpy_s(name, Nsize, n, Nsize);
        cout << "[Con 2] for name:         " << (*this).name <<
            ", address: this=" << this << "\n\n";
    }
    void print() { cout << " [print], CopyPtr name:   " << (*this).name <<
        ", address: this=" << this << "\n\n"; }
    void setName(const char* setP) { strncpy_s(name, Nsize, setP, Nsize); }
};

int main()
{
    vecC CstrName("Cname"); CstrName.print();//declare CstrName and print out name = Cname
    vecC CopyCstr("blank"); CopyCstr.print();//declare CopyCstr and print out name = blank
    CopyCstr = CstrName; CopyCstr.print();//Copy CstrName into CopyCstr and print CopyCstr name = Cname
    CstrName.setName("delete");//set name in CstrName = delete
    CstrName.print(); CopyCstr.print();//Print out both to see what happen to name in CopyCstr. Works!
    cout << "\n\n";
    vecP PtrName("Ptname"); PtrName.print();
    vecP CopyPtr("blank"); CopyPtr.print();
    CopyPtr = PtrName; CopyPtr.print();
    PtrName.setName("delete");
    PtrName.print(); CopyPtr.print();//name in CopyPtr got changed to delete because one the address name
                                     //got copied over, so changing the *name change for both.
    return 0;
}

The print out :
Constructor compare.jpg


If you want to, you can run the program, you can see the address of the Objects are correct. Compare the top 7 lines to the bottom 7 lines, the last line is the problem.

I am very happy, I kept reading using pointer to copy will present a problem in the book, I just cannot put my finger on it till now! I put the explanation in comment in the program. A day well spent for Christmas Eve!
 
  • #11
A notable advantage to using a fixed-length array as a data member, instead of using a pointer to a dynamically-allocated array using new, is that you don't need to write your own destructor, copy constructor, and assignment operator. If you don't write your own versions of these functions, the compiler automatically generates its own versions which are sufficient for classes whose data members are "plain old data" (POD), not pointers, or are classes that themselves have properly defined these functions (e.g. std::string and std::vector).

Conversely, if a class has data members that are pointers, then you generally need to write your own versions of all three: destructor, copy constructor, and assignment operator. This is known as the "rule of three"

Modern versions of C++ also have a "move constructor" and a "move assignment operator" which expand this to a "rule of five" (also described in the Wikipedia page that I linked to).
 
  • Like
Likes sysprog, Vanadium 50, Jarvis323 and 1 other person
  • #12
jtbell said:
A notable advantage to using a fixed-length array as a data member, instead of using a pointer to a dynamically-allocated array using new, is that you don't need to write your own destructor, copy constructor, and assignment operator. If you don't write your own versions of these functions, the compiler automatically generates its own versions which are sufficient for classes whose data members are "plain old data" (POD), not pointers, or are classes that themselves have properly defined these functions (e.g. std::string and std::vector).

Conversely, if a class has data members that are pointers, then you generally need to write your own versions of all three: destructor, copy constructor, and assignment operator. This is known as the "rule of three"

Modern versions of C++ also have a "move constructor" and a "move assignment operator" which expand this to a "rule of five" (also described in the Wikipedia page that I linked to).
Thanks Jtbell

Do you know your post created a "stepping" monster?! I just love the way you write your program displaying step by step what's going on. It's the extra time well spent.

Yes, that's what the book talked about needing the Copy Constructor.I have a question about displaying the pointer, I want to display the ADDRESS it is pointing to but I can't. Here is the short program I just wrote:
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;

int main()
{
    char* ptr;
    ptr = new char[Nsize];
    char Ar[Nsize] = "test";
    strncpy_s(ptr, Nsize, Ar, Nsize);
    cout << " ptr = " << ptr << ", *ptr = " << *ptr << ", &ptr = " << &ptr << "\n\n";
    return 0;
}

When I cout << ptr, I got "test", and when I cout << *ptr, I got t! &ptr is the address of the ptr, not where it points to. I want to display what is the content the ptr ...which is the address of the memory. How do I do that?

I can only display the address that the pointer is pointing using Immediate window in Debug.
Pointer to address.jpg


Thanks
 
Last edited:
  • #13
jtbell said:
A notable advantage to using a fixed-length array as a data member, instead of using a pointer to a dynamically-allocated array using new, is that you don't need to write your own destructor, copy constructor, and assignment operator.
This is a very important point about whether deep copy is needed or not. If a class data members contain all of their data, deep copy is not needed. OTOH, if any of the class data members are pointers, then an object is not self contained, and deep copy is required.
yungman said:
When I cout << ptr, I got "test", and when I cout << *ptr, I got t!
This is because the stream insertion operator, <<, has overloads for char pointers, and for chars. Since the type of ptr is char*, the overload to print a C string is used. Since the type of *ptr is char, the overload to print a single character is used.
yungman said:
&ptr is the address of the ptr, not where it points to. I want to display what is the content the ptr ...which is the address of the memory. How do I do that?
A quick and dirty way would be to cast &ptr as an unsigned int for 32-bit code (which is what you are doing) or as an unsigned long for 64-bit code. For the first suggested, something like this:
cout << (unsigned int)&ptr;

There are probably other ways, but this is what comes to mind at the moment.
 
  • Like
Likes sysprog, Vanadium 50 and yungman
  • #14
jtbell said:
A notable advantage to using a fixed-length array as a data member, instead of using a pointer to a dynamically-allocated array using new, is that you don't need to write your own destructor, copy constructor, and assignment operator. If you don't write your own versions of these functions, the compiler automatically generates its own versions which are sufficient for classes whose data members are "plain old data" (POD), not pointers, or are classes that themselves have properly defined these functions (e.g. std::string and std::vector).

Conversely, if a class has data members that are pointers, then you generally need to write your own versions of all three: destructor, copy constructor, and assignment operator. This is known as the "rule of three"

Modern versions of C++ also have a "move constructor" and a "move assignment operator" which expand this to a "rule of five" (also described in the Wikipedia page that I linked to).
I so wish the book would talk about the rule of 3! Would save me a lot of time. I was just afraid of the hit and misses and kept looking at it.

Funny that the book kept using example of pointer to new char example after example if the author knew it's INFERIOR. Not only causing potential problem, two extra lines of code to create new memory and needing of a Destructor to delete the memory. Just pass Object instead of pointer saves all the trouble. creating new memory doesn't even save a piece of memory, just two extra wasted steps.

Thanks
 
  • #15
yungman said:
I so wish the book would talk about the rule of 3!
The book you're using is a brief intro to C++, as I recall. You can't expect it to include all the nuances of the language in a brief introduction.
yungman said:
Funny that the book kept using example of pointer to new char example after example if the author knew it's INFERIOR. Not only causing potential problem, two extra lines of code to create new memory and needing of a Destructor to delete the memory.
I don't think anyone said it's inferior.
yungman said:
Just pass Object instead of pointer saves all the trouble. creating new memory doesn't even save a piece of memory, just two extra wasted steps.
The only reason you can get away with what you're doing with your C-string members is that they are all fixed-size arrays of type char. If they were arbitrary C-strings, and the members were the addresses of the first character of the strings, you would need to allocate memory in a copied-to object, and would need to delete the memory when the object is destroyed.
 
  • Like
Likes sysprog and Vanadium 50
  • #16
Mark44 said:
This is a very important point about whether deep copy is needed or not. If a class data members contain all of their data, deep copy is not needed. OTOH, if any of the class data members are pointers, then an object is not self contained, and deep copy is required.
This is because the stream insertion operator, <<, has overloads for char pointers, and for chars. Since the type of ptr is char*, the overload to print a C string is used. Since the type of *ptr is char, the overload to print a single character is used.
A quick and dirty way would be to cast &ptr as an unsigned int for 32-bit code (which is what you are doing) or as an unsigned long for 64-bit code. For the first suggested, something like this:
cout << (unsigned int)&ptr;

There are probably other ways, but this is what comes to mind at the moment.
Hi Mark, Merry Christmas

I tried (unsigned int)&name for pointer name, the address is funny but still address is different between PtrName.name and CopyPtr.name.

Here is the program
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;
class vecC {
public:
    char name[Nsize];
    vecC(const char* desc){   strncpy_s(name, Nsize, desc, Nsize); }
    void print() {  cout << " " << name <<
        ", address: name=" << &name << "\n\n"; }
    void setName(const char* setC) { strncpy_s(name, Nsize, setC, Nsize); }
};
class vecP {
public:
    char*name;
    vecP(const char* n) {name = new char[Nsize];strncpy_s(name, Nsize, n, Nsize);}
    void print() { cout << " " << (*this).name <<", address: name=" << (unsigned long int)&name << "\n\n"; }
    void setName(const char* setP) { strncpy_s(name, Nsize, setP, Nsize); }
};

int main()
{
    vecC CstrName("Cname"); cout << " Print CstrName:\t\t "; CstrName.print();//declare CstrName and print out name = Cname
    vecC CopyCstr("blank"); cout << " Print CopyCstr:\t \t"; CopyCstr.print();//declare CopyCstr and print out name = blank
    CopyCstr = CstrName; cout << " Print CopyCstr=CstrName:\t ";  CopyCstr.print();//Copy CstrName into CopyCstr and print CopyCstr name = Cname
    CstrName.setName("delete");//set name in CstrName = delete
    cout << " Print new CstrName:\t\t "; CstrName.print();
    cout << " Print CopyCstr after changing: "; CopyCstr.print();//Print out both to see what happen to name in CopyCstr. Works!
    cout << "\n\n";
    vecP PtrName("Ptname"); cout << " Print PtrName:\t \t\t"; PtrName.print();
    vecP CopyPtr("blank"); cout << " Print CopyPtr: \t\t"; CopyPtr.print();
    CopyPtr = PtrName; cout << " Print CopyPtr=PtrName: \t"; CopyPtr.print();
    PtrName.setName("delete");
    cout << " Print new PtrName: \t\t"; PtrName.print();
    cout << " Print CopyPtr after changing: "; CopyPtr.print();//name in CopyPtr got changed to delete because one the address name
                                     //got copied over, so changing the *name change for both.
    return 0;
}
I put your suggestion in line 17. The number doesn't look right and also you can see it's different from PtrName. The whole point is if you assign a Object with pointer, you copy the address of the pointer that result in both pointing at the same memory location. I don't see that. Here is the printout:
Pointer to address.jpg

I think something is still not right using (unsigned long int)&name. Any other suggestion?

Thanks
 
  • #17
You're printing the addresses in decimal. It's probably better to print them in hex.
  1. Add #include <iomanip>
  2. Change the print() function as follows:
    C++:
    void print() { cout << " " << (*this).name << std::hex << ", address: name=" << (unsigned )&name << "\n\n"; }
Since you are writing 32-bit code, the pointer will fit in a 32-bit type; e.g., unsigned (which is short for unsigned int). You don't need unsigned long (or unsigned long int - same same) for what you're doing.
 
  • #18
Hi Mark

I change to what you suggested, it looks better, but the address doesn't match as you can see. For it to be SHALLOW copy, the two has to be the same pointed by the red arrow.
Pointer to address.jpg


Thanks
 
  • #19
You're printing the address of the pointer, not the pointer. You should remove the & before name in the print statement. As shown in the updated diagram, the pointer is contained in a, and its address (&name) is the same as the address of a (&a). But the pointers value (name) holds an address to the string.

arr.png


https://ideone.com/Kdd0AJ
 

Attachments

  • arr.png
    arr.png
    9.7 KB · Views: 134
Last edited:
  • Like
Likes sysprog
  • #20
Jarvis323 said:
You're printing the address of the pointer, not the pointer. You should remove the & before name in the print statement. As shown in the updated diagram. The pointer is contained in a, and its address (&name) is the same as the address of a (&a). But the pointers value (name) holds an address to the string.

https://www.physicsforums.com/attachments/275125
I know what you mean, I did try printing name, that is the most logical way of doing it. It did NOT work. It only print out the the "name"!

I even try to print *(&ptr) which is literally the dereferencing of the address of ptr! and still won't work!
C++:
#include <iostream>
#include <cstring>
using namespace std;
const int Nsize = 51;

int main()
{
    char* ptr;
    ptr = new char[Nsize];
    char Ar[Nsize] = "test";
    strncpy_s(ptr, Nsize, Ar, Nsize);
    cout << " ptr = " << *(&ptr) << ", *ptr = " << *ptr << ", &ptr = " << &ptr << "\n\n";
    return 0;
}

I don't know what else to do. In order to proof it is SHALLOW COPY, both pointer name have to be pointing to the same memory location.

Thanks
 
  • #21
Jarvis323 said:
You're printing the address of the pointer, not the pointer.
Right.
Also, there's no need for (*this).name in your print() routine. All you need instead is just name.
Furthermore, clumping several statements on the same line makes debugging harder, since both or all three statements execute in the debugger, not just one at a time.

Finally, many of your comments are unhelpful. The first line in main looks like this:
C++:
vecC CstrName("Cname"); cout << " Print CstrName:\t\t "; CstrName.print();//declare CstrName and print out name = Cname
Clearly CstrName is being declared, so there's no reason to have a comment that merely restates the obvious. And the part that says "print out name = Cname" doesn't reflect what the code does, which is to print the text that's in the name member of the CstrName object, and the address of the string.
 
  • Like
Likes sysprog
  • #22
Mark44 said:
Right.
Also, there's no need for (*this).name in your print() routine. All you need instead is just name.
Furthermore, clumping several statements on the same line makes debugging harder, since both or all three statements execute in the debugger, not just one at a time.

Finally, many of your comments are unhelpful. The first line in main looks like this:
C++:
vecC CstrName("Cname"); cout << " Print CstrName:\t\t "; CstrName.print();//declare CstrName and print out name = Cname
Clearly CstrName is being declared, so there's no reason to have a comment that merely restates the obvious. And the part that says "print out name = Cname" doesn't reflect what the code does, which is to print the text that's in the name member of the CstrName object, and the address of the string.
cout << name will only give me the name of the Object. I know exactly what you are getting. If name is a pointer, then the CONTENT in &name contain the address of the location it is pointing to. But if you do cout << name, you literally get the NAME of the object!

The way I display is the most helpful already. The left most Print follow by the name of the object. then show what is in the name. then the address of name. It's logical if you stop and read it. This tells you what Object is being worked on, what is the string literal stored in name, and then what is the ADDRESS of name!

Here is the printout. This is as good as it gets!
Printout.jpg
 
Last edited:
  • #23
yungman said:
cout << name will only give me the name of the Object. I know exactly what you are getting. If name is a pointer, then the CONTENT in &name contain the address of the location it is pointing to. But if you do cout << name, you literally get the NAME of the object!

The way I display is the most helpful already. The left most Print follow by the name of the object. then show what is in the name. then the address of name. It's logical if you stop and read it. This tells you what Object is being worked on, what is the string literal stored in name, and then what is the ADDRESS of name!
Look at the last version of the diagram I made carefully. name itself is a pointer (address). &name is a pointer to a pointer. I made a sample program that goes with the diagram, if this helps.

https://ideone.com/Y22Kbr
C:
#include <iostream>
using namespace std;

struct VecP {
    char *name;
    VecP() {
        name = new char[ 10 ];
    }
    ~VecP() {
        delete [] name;
    }
};

struct VecC {
    char name[ 10 ];
};

int main() {
    VecP a;
    VecC b;

    cout << (unsigned long long) a.name << ", "    // address of the char array
         << (unsigned long long) &(a.name) << ", " // address of the address of the char array
         << (unsigned long long) &a << endl;       // address of the struct/class

    cout << (unsigned long long) b.name << ", "    // address to the char array
         << (unsigned long long) &(b.name) << ", " // address of the address of the char array
         << (unsigned long long) &b << endl;       // address of the struct/class
}

Code:
Output:
94788392345200, 140726081602960, 140726081602960
140726081602974, 140726081602974, 140726081602974
 
Last edited:
  • Like
Likes sysprog and Vanadium 50
  • #24
yungman said:
cout << name will only give me the name of the Object. I know exactly what you are getting. If name is a pointer, then the CONTENT in &name contain the address of the location it is pointing to. But if you do cout << name, you literally get the NAME of the object!
That's not what I was talking about. What I was saying is that you don't need to write (*this).name -- name all by itself will do just fine.
yungman said:
The way I display is the most helpful already. The left most Print follow by the name of the object. then show what is in the name. then the address of name. It's logical if you stop and read it. This tells you what Object is being worked on, what is the string literal stored in name, and then what is the ADDRESS of name!
And this isn't what I was talking about either. What I was saying is that your comments are unhelpful. A comment should never restate what is obvious. For example, here's a useless comment:
C++:
vecC CstrName("Cname"); //declare CstrName
Anyone with the most basic knowledge of C or C++ can see that CstrName is being declared. There is no need whatsoever for that comment.
 
  • Like
Likes sysprog, pbuk and Vanadium 50
  • #25
Mark44 said:
That's not what I was talking about. What I was saying is that you don't need to write (*this).name -- name all by itself will do just fine.
And this isn't what I was talking about either. What I was saying is that your comments are unhelpful. A comment should never restate what is obvious. For example, here's a useless comment:
C++:
vecC CstrName("Cname"); //declare CstrName
Anyone with the most basic knowledge of C or C++ can see that CstrName is being declared. There is no need whatsoever for that comment.
I did everything that is suggested already. What you show early on is only one that gave an address, but it showed it's different, so that it doesn't proof what the book said that both the names of PtrName and CopyPtr point to the same location.

I am trying to proof what the book said. The result is correct, but I cannot proof both pointing to the same location that cause the problem.

The comment in the program is NOT for others to see, it's for me to copy into my notes. The code is very obvious, it cannot be more obvious than that. I just hurry to copy and post here, did not remove the comments. Those has no bearing to the question.

Here are the two pages I want to proof, that both name pointing to the same location.
 

Attachments

  • Copy C1.jpg
    Copy C1.jpg
    38.2 KB · Views: 136
  • Copy C2.jpg
    Copy C2.jpg
    43.1 KB · Views: 133
  • #26
yungman said:
I did everything that is suggested already. What you show early on is only one that gave an address, but it showed it's different
They are different because you have a bug in your code, and this has already been pointed out by @Jarvis323.
You had this in the body of your print() function:
C++:
cout << " " << name << std::hex << ", address: name=" << (unsigned long)&name << "\n";
Remove the & in front of name.
yungman said:
The comment in the program is NOT for others to see, it's for me to copy into my notes.
You posted the code, so it's not just for you to see. If you copy stuff like the comment below into your notes, you're including useless comments. It's a good thing generally to include comments, but comments should be informative, and not just state the obvious.
C++:
vecC CstrName("Cname"); //declare CstrName
 
  • Like
Likes glappkaeft and Vanadium 50
  • #27
Mark44 said:
They are different because you have a bug in your code, and this has already been pointed out by @Jarvis323.
You had this in the body of your print() function:
C++:
cout << " " << name << std::hex << ", address: name=" << (unsigned long)&name << "\n";
Remove the & in front of name.
You posted the code, so it's not just for you to see. If you copy stuff like the comment below into your notes, you're including useless comments. It's a good thing generally to include comments, but comments should be informative, and not just state the obvious.
C++:
vecC CstrName("Cname"); //declare CstrName
I followed what you gave in post 17 to have the &. I really don't understand this.

Ha ha, I am balancing my Christmas party and here!
 
  • #28
OK, I put in separate post as this one from Mark actually gives me same address for both as shown. This is what I want to see. I use last thing Mark suggested without &:
C++:
    void print() { cout << "name: " << name <<  ", &name= " << &name  <<
        ", address inside name: " <<  std::hex <<(unsigned long)name << "\n\n"; }
the result is:
Pointer to address.jpg


This is from Mark's last suggestion without &. This is what I am looking, that the last two address in name is the SAME! IF this is correct, that shows the address of name is the same in PtrName and CopyPtr. Then changing name in PtrName will change CopyPtr.
 
Last edited:
  • #29
Good morning.
I was searching online to find how to display the address the pointer pointing to. The other way is:
cout << (void*)name;. I work also. This confirm the result:
C++:
    void print() { cout << "name: " << name <<  ", &name= " << &name <<
        ", address inside name from Mark: "<< std::hex  << (unsigned long)name <<
        ", using (void*)name: " << (void*)name << "\n\n"; }
Pointer to address.jpg


You can see both Mark's and the (void*)name produce the same address. This concludes this thread.

What do you call this? I never learn this before, I would like to learn a little more. Even the article only show HOW to do it with no explanation. I don't understand what Mark showed cout << std::hex << (unsigned long)name;. what are these?

Thanks
 
  • #30
yungman said:
What do you call this? I never learn this before, I would like to learn a little more.
It's really nothing more than casting a number so that it appears in a different form, or in this case, to prevent the << operator from interpreting the address as the address of a string, and thereby using the << overload that prints the characters at that address.
Either of the casts will work -- the one I used or the (void *) that you used. The whole point is to print the address, not the characters it points to.
yungman said:
I don't understand what Mark showed cout << std::hex << (unsigned long)name;. what are these?
hex is one of many manipulators that are declared in the iomanip header.
 
  • Like
Likes sysprog and yungman
  • #31
Note that #include <iomanip> is the same place where you get setw(), setprecision() and the other stream manipulators that Gaddis discusses in section 3.8.
 
  • Like
Likes sysprog and yungman
  • #32
@Mark44 maybe it's archaic of me to do so, but I put a comment on every line of my mainframe or PC assembly language code, even if what the instruction is doing is obvious or should be obvious ##-## I do that based on the it can't hurt principle ##-## if a full explanation is warranted, I'll write it on non-instruction lines ##-## otherwise, I don't see why I should unnecessarily let an unexplained instruction go by.
 
  • #33
sysprog said:
@Mark44 maybe it's archaic of me to do so, but I put a comment on every line of my mainframe or PC assembly language code, even if what the instruction is doing is obvious or should be obvious ##-## I do that based on the it can't hurt principle ##-## if a full explanation is warranted, I'll write it on non-instruction lines ##-## otherwise, I don't see why I should unnecessarily let an unexplained instruction go by.
I wrote those comments for copying into my notes. I know I will forget what I am doing in the future thanks to the old brain. I just want to explain it in my notes. Actually here is the page of notes I just put in yesterday. You can see the same program with comments.

I put even more comments in the Overloading Constructor as you can see. I even use different colors for words as it's easier for me to read so I won't jump lines.

For me, it's a whole lot more important to actually print out a detail description when running the program where the code goes. I put in extra effort to line things up and make it easy to compare
 

Attachments

  • Constructors.docx
    81.1 KB · Views: 122
Last edited:
  • Like
Likes sysprog
  • #34
In assembly language you work with registers which have fixed names and there is no such thing as a type so a comment like
Code:
mov ebx, message ;Set ebx to point to the beginning of a null-terminated message string.
is worthwhile. In a high level language, code like
C++:
char[] message = "This is a message";
needs no comment, and there are at least two good reasons you should NOT add unnecessary comments.
 
  • Like
Likes sysprog
  • #35
pbuk said:
In assembly language you work with registers which have fixed names and there is no such thing as a type so a comment like
Code:
mov ebx, message ;Set ebx to point to the beginning of a null-terminated message string.
is worthwhile. In a high level language, code like
C++:
char[] message = "This is a message";
needs no comment, and there are at least two good reasons you should NOT add unnecessary comments.
I miss assembly languages. I don't understand why they don't use assembly language more, it's a lot smaller, a whole hell of a lot faster. People don't need new version of software every day. I am not going to start the ranting how the newer stuffs with software and firmware are slow and all.
 

Similar threads

  • Programming and Computer Science
3
Replies
89
Views
4K
  • Programming and Computer Science
Replies
4
Views
1K
  • Programming and Computer Science
Replies
5
Views
885
  • Programming and Computer Science
Replies
17
Views
1K
Replies
10
Views
961
  • Engineering and Comp Sci Homework Help
Replies
2
Views
949
  • Programming and Computer Science
Replies
31
Views
2K
  • Programming and Computer Science
Replies
18
Views
2K
  • Programming and Computer Science
3
Replies
75
Views
4K
  • Programming and Computer Science
2
Replies
35
Views
2K
Back
Top