This is a simple operator overloading program I learned and I can't understand exactly why the parameterized constructor is using '*st' and not just 'st' or '&st'.
Now, I know the difference between passing by reference, address and value.
In the given example, I passed a string. If it was passing by reference, the argument in the parameterized constructor would have been '&st'. I'm not sure if it is passing the string by address.
Basically, I don't know how the code is working there. Please explain that and also why using '&st' in place of '*st' isn't working.
class tyst
{
int l;
char *p;
public:
tyst(){l=0;p=0;}
tyst(char *st)
{
l=strlen(st);
p = new char[l];
strcpy(p,st);
}
void lay();
tyst operator + (tyst b);
};
void tyst::lay()
{
cout<<p<<endl;
}
tyst tyst::operator+(tyst b)
{
tyst temp;
temp.l=l+b.l;
temp.p = new char[temp.l];
strcpy(temp.p,p);
strcat(temp.p,b.p);
return temp;
}
int main()
{
tyst s1("Markus Pear");
tyst s2("son Notch");
tyst s3;
s3=s1+s2;
s3.lay();
return 0;
}
So, I'd really appreciate if anyone can clear this up for me.
st is a C-style string. Passed by value
tyst(char st)
you would merely get a single character.
Passed by reference
tyst(char & st)
You would also get only a single character, but you could modify it. Not so useful in this case. You could also pass in a reference to a pointer, but I don't see much use to that, either.
How this is working
tyst(char * st)
says that the function will take a pointer, and that pointer may be pointing to a single character, the first of an unknown number of characters, absolutely nothing, or complete garbage. The last two possibilities are why use of references is preferred over pointers, but you can't use a reference for this. You could however use a std::string. In C++, this would often be the preferred approach.
Inside tyst, the assumption that an unknown, but null-terminated, number of characters is pointed at, and this is almost what is being provided. Technically, what you are doing here with
tyst s1("Markus Pear");
is illegal. "Markus Pear" is a string literal. It may be stored in non-writeable memory, so it is a const char *, not a char *.
The constructor is expecting a pointer to a c-string (null terminated character array). Applying pointer arithmetic to it will allow access to the entire string. Note that new[] returns a pointer to the first element; it is (one way) how pointers are used.
Aside from the syntax errors, it makes no sense to pass a single character by reference to the class. It isn't interested in a single character, it is interested in where the beginning of the array is.
It would be like asking somebody what their home address is, and they give you a rock from their lawn.
Related
I have to call a method with the following signature:
int sendTo(const void* buffer, int length, const SocketAddress& address, int flags=0);
My first question is:
What does const void* buffer exactly mean? My intention is: it means that it is a constant (unmodifiable) pointer which can point to anything. ist this somehow right?
Second question:
The purpose of this method is, obviously, to send data over a socket.
The first parameter is the data, the second is the length of that data.
If I want to pass the string "hello" as the first parameter, how would I do this?
My idea:
char hello_str[1024] = "hello"
socket.sendTo(hello_str, sizeof(hello_str),.....);
would this work? But this way I have a way too big char array.
How can I create the array with the right size?
Recall that const protect its left side unless there's nothing to it's left, then it protects its right side. Applying this to your code we'll get that const is protecting void* buffer. That means that the value it points to cannot be modified:
The first is a pointer to a const variable - The pointer can be changed.
The second is a const pointer to a variable - The value can be changed.
This will work, you can easily try it.
And as others already answered, creating it with the right size is done simply by:
char hello_str[] = "hello";
it means that it is a constant (unmodifiable) pointer which can point to anything
No, that would be void *const. It's rather a pointer-to-anything, where the pointee (the "anything" itself) can't be modified.
would this work?
yes, apart from the missing semi-colon.
How can i create the array with the right size?
char hello_str[] = "hello";
or even
const char hello_str[] = "hello";
First question: H2C03 is right, you should make the type be void * const to prevent the pointer from being modified.
Second question: You have some options here, depending on exactly what you are doing. Here are two examples that would work:
char hello_str[] = "hello"
socket.sendTo(hello_str, sizeof(hello_str)-1,...);
socket.sendTo(hello_str, strlen(hello_str),...);
In the first call to sendto, we are calculating the size of the string at compile time. We subtract 1 in order to avoid sending the null termination character at the end of the string. In the second case, we are computing it at runtime by calling the standard strlen function which is available in C and C++.
What does const void* buffer exactly mean?
It's an untyped pointer (that's another way of saying that it can point to anything). The value it points to cannot be modified (that's not entirely correct, but at least that is what you should think when you see that). The pointer itself can change however:
const void * buffer = &a;
buffer = &b; // this is valid!
Besides that, your function call is completely correct.
You can do :
const char hello_str[] = "hello"; // Don't forget the const
socket.sendTo(hello_str, sizeof(hello_str)-1,.....);
// or socket.sendTo(hello_str, strlen(hello_str),.....);
To answer to your questions :
What does const void* buffer exactly mean? My intention is: it means that it is a constant (unmodifiable) pointer which can point to anything. ist this somehow right?
No, That would be void* const. const void* means that it is the pointee that cannot be modified.
You may read this.
I'm trying to understand a part of my professor's code. He gave an example for a hw assignment but I'm not sure how to understand this part of the code..
Here is the code:
void addTask(TaskOrAssignment tasks[], int& taskCount, char *course, char *description, char *dueDate)
{
tasks[taskCount].course = course;
tasks[taskCount].description = description;
tasks[taskCount].dueDate = dueDate;
taskCount++;
}
Question: Is "tasks[taskCount].course = course;" accessing or declaring a location for char course?
I hope I could get this answered and I'm pretty new to this site too.
Thank you.
tasks[taskCount].course = course;
Let's break this down a piece at a time. First of all, we are using the assignment operator (=) to assign a value of one variable to another variable.
The right hand side is pretty simple, just the variable named course which is declared as a char*.
It is assigned to the variable tasks[taskCount].course. If you look at the parameters of the method, you can see that tasks is declared as an array of TaskOrAssignment objects. So tasks[taskCount] refers to one of the elements of this array. The .course at the end refers to a field named course in that object. Assuming that this code compiles, that field is declared as a char* in the TaskOrAssignment class.
Most likely, both course variables represent a string of characters. (This originates from C.) When all is said and done, both course and tasks[taskCount].course point to the same string buffer.
course is a char pointer, it points to the block of memory in stack or heap storing the '\0' terminated string.
tasks[taskCount].course is also a char pointer, the assignment just lets tasks[taskCount].course point to same memory address that course does.
course is a char* (a pointer to char). Presumably, the course member of TaskOrAssignment is also a char*. All that line does is assign the value of course to the member course of the taskCountth element in the array.
Presumably, the course argument is intended to be a pointer to the first character in a null-terminated C-style string. So after this assignment, the course member of the array element will point at that same C-style string. However, of course, the pointer could really be pointing anywhere.
Pointers have always made me blank about the logic I intend to use in code, If someone can help me understand a few concepts that would be really helpful. Here's a code snippet from my program,
vector <char> st;
char *formatForHtml(string str, string htmlTag)
{
string strBegin;
strBegin = "<";
strBegin.append(htmlTag);
strBegin.append(">");
strBegin.append(str);
string strEnd = "</";
strEnd.append(htmlTag);
strEnd.append(">");
strBegin.append(strEnd);
st.resize(strBegin.size());
for (int i =0;i <strBegin.size();i++) {
st[i] = strBegin.at(i);
}
return &st[0];
}
In the code above if I have to return address of st[0], I have to write the function of type char *. I need to know the reason to do so, also if address is the integer value why can I not define function as an int type?
P.S. It's a beginner level doubt.
You don't tell us what st is, so we can't tell whether the code is
totally incorrect, or just bad design. If st is a typo for str
(just guessing, since str isn't used anywhere), then you have
undefined behavior, and the program is incorrect, since you're returning
a pointer into an object which has been destructed. At any rate, a
function like formatForHtml should return an std::string, as a
value, and not a pointer (and certainly not a pointer to a non-const).
I might add that you don't use a loop to copy string values character by
character. std::string acts as a normal value type, so you can just
assign: st = strBegin;.
EDIT:
Just for the record, I've since reexamined your code. The natural way
of writing it would be:
std::string
formatForHtml( std::string const& cdata, std::string const& tag )
{
return '<' + tag + '>' + cdata + "</" + tag + '>';
}
No pointers (at least not visible---in fact, "+ operator), and full use of
std::strings facilities.
I have to write the function of type 'char *' I need to know the reason to do so
There's no reason to do so. Just return a std::string.
From the looks of your code, st is a std::vector<char>. Since std::vector has continuous memory, &st[0] is the address of the first char in the vector, and thus points to the not null-terminated string that the vector represents, which isn't very helpful outside the function because you can't find the length.
That's awkward code, you're expecting 'str' as an argument, but then you return its memory location? Why not return the string itself?
Your code there has a few typos. (Did you mean 'str' when you typed 'st'? If not, then where is 'st' defined?)
As for why you can't define the function as "int" type, that is because an "int" is a different type to "pointer to char".
Personally, I would return 'string', and just have a 'return str' at the end there.
Pointer is pointer, not integer value. Code is right if and only if st is global variable or declared as static in this function. But return string is preferably, than return pointer.
Why don't you use string as return type for your function?
First: a pointer is an adress of something lying in memory, so you can't replace it with an integer (only with some dirty tricks).
Second: &st[0] is the adress of the internal buffer the string uses to store its content. When st goes out of scope (or is reused for the next call), it will be overwritten or given back to the heap manager, so the one calling this function will end with some garbage.
Btw, most of your function does unnessesary work which the string class can do by itself (for example copiing strBegin to st).
Simple.
string str
is something that contains a bunch characters.
str[0]
return the first character.
Therefore,
&str[0]
gives you the address of the first character, therefore it's a "char *" --- "char" being whatever the pointer points to, "*" being the "address of" part of the pointer. The type of the pointer is about the object being pointed to.
Also, addresses may be just "integers" on the hardware level (everything is an integer... except for integers themselves, they are a bunch of bools), but that doesn't mean anything for a higher level language. For a higher level language, a pointer is a pointer, not an integer.
Treating one as another is almost always an error, and C++11 even added the nullptr keyword so we don't have to rely on the one valid "pointer is an integer" case.
And btw, your code won't work. "str" only exists for the duration of the function, so when the function returns "str" ceases to exist, which means the pointer you have returned points into a big black nowhere.
When declaring a function, what is the difference between the parameters string* and string&? I know that string s would make a copy of the string s and pass it by value, but it seems that on many websites, they refer to string* s and string& s as both passing by reference. I am new to C++ and this is the only thing that i have not been able to figure out myself. Thanks in advance :)
Decent explanation here:
http://www.cprogramming.com/tutorial/references.html
(Hint: there is more to it than "it looks different")
Passing by pointer string* s passes in an address, so s is not of type string, it's an address. If you dereferenced it, that is used some expression including *s, then *s is of string type.
When passing by reference string& s, s is of type string, so no dereferencing is necessary.
Lots of almost right answers. Many are right for particular implementations but rely on unspecified behavior on the part of a compiler.
Aside from the . vs ->:
pointers are first class objects and references are not. You can take the address of a pointer but you cannot take the address of a reference (you'll get the address of the referenced object)
references always refer to the same object for the duration of their lifetime. Non-const pointers can change.
References cannot be to a "null object". You can write code that does this but you're relying on unspecified compiler behavior
You can do arithmetic on pointers
In general, the language spec says very little about references, purposefully giving compiler writers a lot of latitude in implementaiton. The fact that they operate a lot like const pointers is not guaranteed by the spec.
I find pointer parameters quite useful in two ways:
The caller has to pass a pointer which could very well be the address of an automatic variable. This makes it obvious to the person reading the calling code that the variable whose address is being passed is likely to change.
Pointers can have a NULL value, which acts like a sentinel. References cannot do that. For example, in your own example of string & versus string *, an empty string could be an acceptable value for the variable and hence useless as a sentinel. However, a NULL value for the pointer parameter tells your function that the string * argument was not set by the caller. The function that receives a string & has no way to determine if the caller has not set the value or is content with the default initialized value.
The main difference is how the function will be called. Consider these examples:
void f(string *s)
{}
int main() {
string s;
f(&s);
}
and the reference version:
void f(string &s) { }
int main() {
string s;
f(s);
}
So the function call looks different...
`
I'm currently reading through Accelerated C++ and I realized I don't really understand how & works in function signatures.
int* ptr=#
means that ptr now holds the address to num, but what does that mean?
void DoSomething(string& str)
from what I understand that is a pass by reference of a variable (which means passing the address) but when I do
void DoSomething(string& str)
{
string copy=str;
}
what it creates is a copy of str. What I thought it would do is raise an error since I'm trying to assign a pointer to a variable.
What is happening here? And what is the meaning of using * and & in function calls?
A reference is not a pointer, they're different although they serve similar purpose.
You can think of a reference as an alias to another variable, i.e. the second variable having the same address. It doesn't contain address itself, it just references the same portion of memory as the variable it's initialized from.
So
string s = "Hello, wordl";
string* p = &s; // Here you get an address of s
string& r = s; // Here, r is a reference to s
s = "Hello, world"; // corrected
assert( s == *p ); // this should be familiar to you, dereferencing a pointer
assert( s == r ); // this will always be true, they are twins, or the same thing rather
string copy1 = *p; // this is to make a copy using a pointer
string copy = r; // this is what you saw, hope now you understand it better.
The & character in C++ is dual purpose. It can mean (at least)
Take the address of a value
Declare a reference to a type
The use you're referring to in the function signature is an instance of #2. The parameter string& str is a reference to a string instance. This is not just limited to function signatures, it can occur in method bodies as well.
void Example() {
string s1 = "example";
string& s2 = s1; // s2 is now a reference to s1
}
I would recommend checking out the C++ FAQ entry on references as it's a good introduction to them.
https://isocpp.org/wiki/faq/references
You shouldn't know anything about pointers until you get to chapter 10 of Accelerated C++ !
A reference creates another name, an alias, for something that exists elsewhere. That's it. There are no hidden pointers or addresses involved. Don't look behind the curtain!
Think of a guy named Robert
guy Robert;
Sometimes you may want to call him Bob
guy& Bob = Robert;
Now Bob and Robert both refer to the same guy. You don't get his address (or phone number), just another name for the same thing.
In your function
void DoSomething(string& str)
{
string copy=str;
}
it works exactly the same, str is another name for some string that exists somewhere else.
Don't bother with how that happens, just think of a reference as a name for some object.
The compiler has to figure out how to connect the names, you don't have to.
In the case of assigning variables (ie, int* ptr = &value), using the ampersand will return the address of your variable (in this case, address of value).
In function parameters, using the ampersand means you're passing access, or reference, to the same physical area in memory of the variable (if you don't use it, a copy is sent instead). If you use an asterisk as part of the parameter, you're specifying that you're passing a variable pointer, which will achieve almost the same thing. The difference here is that with an ampersand you'll have direct access to the variable via the name, but if you pass a pointer, you'll have to deference that pointer to get and manipulate the actual value:
void increase1(int &value) {
value++;
}
void increase2(int *value) {
(*value)++;
}
void increase3(int value) {
value++;
}
Note that increase3 does nothing to the original value you pass it because only a copy is sent:
int main() {
int number = 5;
increase1(number);
increase2(&number);
increase3(number);
return 0;
}
The value of number at the end of the 3 function calls is 7, not 8.
It's a reference which allows the function to modify the passed string, unlike a normal string parameter where modification would not affect the string passed to the function.
You will often see a parameter of type const string& which is done for performance purposes as a reference internally doesn't create a copy of the string.
int* ptr=#
1st case: Since ptr is a memory and it stores the address of a variable. The & operator returns the address of num in memory.
void DoSomething(string& str)
2nd case: The ampersand operator is used to show that the variable is being passed by reference and can be changed by the function.
So Basically the & operator has 2 functions depending on the context.
While pass by reference may be implemented by the compiler by passing the address as a pointer, semantically it has nothing to do with addresses or pointers. in simple terms it is merely an alias for a variable.
C++ has a lot of cases where syntax is reused in different contexts with different semantics and this is one of those cases.
In the case of:
int* ptr=#
you are declaring a variable named ptr with a type of an int * (int pointer), and setting its value to the "address of the variable num" (&num). The "addressof" operator (&) returns a pointer.
In the case of:
void DoSomething(string& str)
you are declaring the first parameter of the DoSomething() method to be of type "reference to string". Effectively, this is the C++ way of defining "pass-by-reference".
Note that while the & operator operates similarly in these cases, it's not acting in the same way. Specifically, when used as an operator, you're telling the compiler to take the address of the variable specified; when used in a method signature, you're telling the compiler that the argument is a reference. And note as well, that the "argument as a reference" bit is different from having an argument that is a pointer; the reference argument (&) gets dereferenced automatically, and there's never any exposure to the method as to where the underlying data is stored; with a pointer argument, you're still passing by reference, but you're exposing to the method where the variable is stored, and potentially exposing problems if the method fails to do a dereference (which happens more often than you might think).
You're inexplicitly copy-constructing copy from str. Yes, str is a reference, but that doesn't mean you can't construct another object from it. In c++, the & operator means one of 3 things -
When you're defining a normal reference variable, you create an alias for an object.
When you use it in a function paramater, it is passed by reference - you are also making an alias of an object, as apposed to a copy. You don't notice any difference in this case, because it basically is the object you passed to it. It does make a difference when the objects you pass contain pointers etc.
The last (and mostly irrelevent to your case) meaning of & is the bitwise AND.
Another way to think about a reference (albeit slightly incorrect) is syntactic sugar for a dereferenced pointer.