how does the structure dereference operator work? - c++

I am a java programmer trying to teach myself c++. Please cut me a little slack if I ask simple questions at first.
I would like to understand how the structure dereference operator works. Specifically, can anyone tell me what the following line of code does in explicit terms?
if (elements[i]->test(arga, argb)) {}
test(arga,argb) is a Boolean function in the same class, and elements is a vector of instances of the element class. Here is the code that immediately surrounds the line above, about which I am interested:
for (unsigned i = 0; i < elements.size(); ++i) {
T arga = INFINITY, argb = INFINITY;
//using namespace std;
//std::cout >> elements[i] >> std::endl;
//std::cout >> test(arga, argb) >> std::endl;
if (elements[i]->test(arga, argb)) {
//some code
}
}
It seems that the if line is testing to see whether or not the boolean returned by test(arga,argb) is part of the given instance of the elements class. But when I try to expose the underlying values of elements[i] or test(arga,argb) with the cout lines above, the compiler throws errors until I comment those lines out. In java, I would be able to fiddle around with this until I found values of each that correspond with each other, and then I would understand the line of code. But I do not know how to figure out what this line of code does in C++. Can anyone give me a clear explanation, preferably supported by a link or two to some references online?

elements[i]->test (arga, argb)
If we break down the statement, reading from left-to-right, we will end up with the below:
access the ith element in an array (or array-like) entity named elements
the element accessed (elements[i]) is a pointer to an object
call the member-function named test on elements[i] and pass it two arguments; arga and argb
if we disregard the fact that you wrote std::cout >> instead of std::cout << (the latter is the correct form), we end up with two reasons for your described errors:
your compiler complains about std::cout << element[i] because no suitable overload is found to handle an entity of the type of element[i] and an std::ostream& (which is the underlying type of std::cout).
your compiler complains about std::cout << test (arga, argb) because there is no function in scope named test that takes two arguments corresponding to arga, argv. test, in your snippet, is a member-function that belongs to an entity, it's not callable by its own.

Welcome to C++.
First, the syntax for output is:
cout<<
instead of
cout>>
You are right in guessing that test is a function that returns boolean.Here elements[i] is a pointer pointing to a struct element which has this test function.
To learn C++, you can use these articles that I wrote.Good luck!

Since numerous respondents told me that I need to provide the code before they can answer, I looked deeper in the code, and re-wrote something which tells me that the line:
if (elements[i]->test(arga, argb)) {}
is a test to see whether or not the boolean member function of elements[i] is true.
The c++ program that I wrote to identify the meaning of -> in this context is:
#include "stdafx.h"
#include <vector>
#include <string>
#include <iostream>
template<typename T>
class Bone
{
public:
std::string myName;
int mySize;
Bone(const std::string &name, const int &size) : myName(name), mySize(size)
{}
bool isBigger(const int &testSize) const
{
if (testSize > mySize) return false;
else return true;
}
};
int main(int argc, char **argv)
{
std::vector<Bone<float> *> bones;
// name, location, size
bones.push_back(new Bone<float>("femur", 10));
bones.push_back(new Bone<float>("ulna", 4));
bones.push_back(new Bone<float>("maxilla", 3));
int testSize = 6;
// test each bone to see if it is bigger than testSize
for (unsigned i = 0; i < bones.size(); ++i) {
if (bones[i]->isBigger(testSize)) {
std::cout << bones[i]->myName; std::cout << " is bigger than testSize! " << std::endl;
}
}
while (!bones.empty()) {
Bone<float> *thisBone = bones.back();
bones.pop_back();
delete thisBone;
}
return 0;
}
Thank you to everyone who led me to figure this out.

Related

Catch and Throw Statements within A function

I have a matrixType File that works fine, but I am now trying to replace the if statements with the try, catch, and throw statements within a function of a class. I am just trying to understand one function so I can apply it to the others. Since I did try to do the try and catch statements but it skipped over the try statement and caused an actual exception that stops the program completely.
The One function I am focusing on is the equal operator
Here is the HeaderFile
#pragma once
#include
#include
#include
#include
#include
#include
using namespace std;
class matrixType
{
private:
int **matrix;
int row;
int col;
public:
const matrixType& operator=(const matrixType& mat);
}
Here is the class.cpp file that currently works
#include "matrixType.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <stdexcept>
#include <limits>
using namespace std;
const matrixType& matrixType::operator=(const matrixType& mat)
{
if (row != mat.row || col != mat.col)
{
cout << "The matrixes are not identical" << endl;
return *this;
}
for (int i = 0; i < row; i++)
{
for (int r = 0; r < col; r++)
{
matrix[i][r] = mat.matrix[i][r];
}
}
return *this;
}
Then this is the source file
#include <iostream>
#include <string>
#include <stdexcept>
#include <limits>
#include "matrixType.h"
using namespace std;
int main()
{
matrixType test1(3, 3);
matrixType test2(2, 2);
test1 = test2;
return 0;
}
So the big question is how do you throw an exception
I tried
Try
{
if(mat.row != row || mat.col != col)
throw exception("The matrixes are not identical")
}
catch (exception & e)
{
cout << e.what << endl;
}
Which caused the actual exception to pop up but when I leave the if statement it works and does not go into a fail state. Does anyone see what I was doing wrong if I replaced the if statement with the code above?
First, a note about the meaning of exceptions. Further down, I'll address what's wrong with your code.
The meaning of throwing an exception in C++, in English, is roughly, "I can't deal with this situation anymore, I'm giving up right now, and I'm hoping that somebody else can deal with this." The meaning of catching an exception is roughly, "oops, somebody screwed up, but I'm going to do something about it now." With this in mind, let's look at how this works in more concrete detail.
Many functions have preconditions, which are things that function always expects to be true before it runs. For example, a squareRoot(double x) function might have a precondition that x must never be negative. When a function's precondition is violated, it's a natural time for that function to say "I'm giving up right now, deal with it!" since somebody who called that function is doing something wrong, and squareRoot can't possibly fix that. This could look like the following:
// precondition: x must not be negative
double squareRoot(double x){
if (x < 0.0){
// precondition is violated
throw std::runtime_error("input to squareRoot was negative");
// the function exits here!
// this point in code is not reachable
}
// otherwise, precondition is satisfied, it's safe to continue
...
return result;
}
elsewhere, in the wild:
void myFunction(){
double x;
cout << "x = ";
cin >> x;
double y = squareRoot(x);
cout << ", y = " << y << '\n';
}
Here, if somebody types in a negative number, then the preconditions of squareRoot are violated, and it throws an exception. This means that squareRoot will not return normally, and neither will myFunction. When exception is thrown, everything is interrupted until you catch the exception, which can happen far outside the current function.
int main(){
try {
myFunction(); // this might throw
// if myFunction() throws, the following output will not happen!
cout << "Thanks! have a nice day.\n";
} catch (std::runtime_error e) {
// if myFunction() does throw, the error lands right here
cout << "Oops! an error occurred: " << e.what() << '\n';
}
return 0;
}
It's important to note that you should only throw exceptions when something is really wrong. Exceptions are not a replacement for ordinary program logic, and they're not a replacement for validating things like user input.
About custom classes:
When you're defining a custom class type, if it has either a copy constructor, copy assignment operator, or destructor, that probably means that your class has sensitive information that needs special care to clean up and keep track of. If you've written at least one of these functions, you should implement all three of them. Otherwise, it's extremely easy to introduce memory leaks, false data sharing, and all kinds of unwanted Undefined Behavior into your program.
About your copy assignment operator:
The purpose of a copy assignment operator, as in a = b; is that after it runs, the left-hand object should be logically identical to the right-hand object, and the right-hand object should not have changed. The previous state of the left-hand object is lost at this point. What exactly logically identical means is a question of what your class is representing.
In the case a simple matrix, I would expect two matrices to be identical when they have the same width, height, and values for all elements, and I would implement a copy assignment operator accordingly. For example:
Matrix& Matrix::operator=(const Matrix& other){
releaseMemory(); // clean up old data
resize(other.rows, other.cols); // allocate new data
for (int i = 0; i < rows; ++i){
for (int j = 0; j < cols; ++j){
this->data[i][j] = other.data[i][j]; // copy each value
}
}
return *this;
}
I leave the implementation of the details to you. You should be able to find great examples and detailed explanations of how to overload operators, write your own copy constructor and destructor, and about good practice in general by reading a good C++ book.
Actually, I figured it out I have to use return statements as it worked when I included a return statement within the catch function.

C++ creating and printing an STL list (instead of a linked list)

So right now I'm trying to implement a list using STL but I'm stuck at what to do for the print function. I've searched for solutions but I'm having a difficult time understanding. I'm having some trouble using iterators in this implementation as well.
Here's my code:
AnyList.h:
class AnyList
{
public:
AnyList();
int getNumOfElem() const;
void insertFront(int data);
void forwardPrint();
private:
list<int> *ptr;
};
AnyList.cpp:
AnyList::AnyList()
{
ptr->begin(); //added
}
int AnyList::getNumOfElem() const
{
return static_cast<int>(ptr->size());
}
void AnyList::insertFront(int data)
{
ptr->push_front(data);
}
void AnyList::forwardPrint()
{
//const list<int> & iter; //removed
list<int>::const_iterator i;
for (i = ptr->begin(); i != ptr->end(); ++i) //changed
{
cout << *i << " ";
cout << endl;
}
}
Main.cpp
int main()
{
AnyList list1, list2;
list1.insertFront(10);
list1.insertFront(11);
list1.insertFront(12);
list1.insertFront(13);
list1.insertFront(14);
cout << "\nList 1: ";
list1.forwardPrint();
}
Any insight would be greatly appreciated. As of now I don't even know how to test whether or not the insertFront function works without the print function.
Edit: made some changes to code and marked them.
Edit2: Just going to include the screenshot of the instructions so there'd be less confusion as to what I'm supposed to be accomplishing here.
Just to reiterate - The project file came with the AnyList class, which includes the private member variable list *ptr and the function getNumOfElements() as an example of a working function. There's a lot more to the main file but I just included the first part that should work if I implement the insertFront and forwardPrint functions correctly.
Edit 3: To further clarify what I believe I am confused about, the examples I see everywhere go something like this:
vector<string> SS;
SS.push_back("The number is 10");
SS.push_back("The number is 20");
SS.push_back("The number is 30");
cout << "Loop by index:" << endl;
int ii;
for(ii=0; ii < SS.size(); ii++)
{
cout << SS[ii] << endl;
}
cout << endl << "Constant Iterator:" << endl;
Which is nice but how do I implement something like this as what the instructions say that I should be doing? What I tried didn't work.
In the forwardPrint function you have this:
const list<int> & iter;
That defines a variable iter that is not an iterator (no matter the name) but a reference to a list. That is wrong in two ways: First you define a variable that has no connection to your actual list. Second you define the variable to be a reference to a list, but without making it actually reference anything.
You should use your member variable as the list instead. So something like
for (i = ptr->begin(); i != ptr->end(); ++i) { ... }
On a slightly related note, why do you have a pointer to a list? A pointer which you don't even initialize? That means if and when you get the program to build you will have undefined behavior as you dereference the uninitialized pointer, which doesn't point anywhere valid.
Don't use a pointer. Use an actual instance instead.
Or, as a couple of comments noted, why wrap the std::list class at all?

What's the grammar meaning of '&buf_pool->watch[0]'?

I read code in buf0buf.cc of mysql's innodb buffer source code here:
link from git hub
And I got this:
&buf_pool->watch[0]
What is the value of the statement? address? or another value?
What does the code mean?(grammar meaning)
Due to operator precedence, this expression is parsed like:
&( (buf_pool->watch)[0] )
In English, the value is the address of the first element of the watch member container in buf_pool.
You can find out.
First of all, let's take the buf_bool variable and look for its declaration. As you can see a few lines above, it's a function parameter:
const buf_pool_t* buf_pool
This means we have to find the definition of the buf_pool_t type. With a mere full-text search, the type definition is not revealed. However, googling for "mysql buf_pool_t" gets us to http://www.iskm.org/mysql56/structbuf__pool__t.html, which in turn tells us that the type is defined in a file called buf0buf.h. That one's also included in the source file you've linked to:
#include "buf0buf.h"
It does indeed contain the definition we are looking for, and that definition includes a member called watch:
struct buf_pool_t{
(...)
buf_page_t* watch;
(...)
};
watch is a pointer to buf_page_t.
So if we go back to the statement in your question:
&buf_pool->watch[0]
watch is interpreted as a pointer to the first element of a buf_page_t array, watch[0] is the first element itself, and the address-of operator yields a pointer to that first element.
So the whole statement reads as:
a pointer to the first element of a buf_page_t array.
Curiously, &buf_pool->watch[0] is equal to buf_pool->watch. Here is a simple (C++11) toy program to verify all of this:
#include <iostream>
#include <typeinfo>
using buf_page_t = int;
struct buf_pool_t {
buf_page_t* watch;
};
int main()
{
const buf_pool_t example = { new buf_page_t[1] };
const buf_pool_t* buf_pool = &example;
std::cout << typeid(&buf_pool->watch[0]).name() << "\n";
std::cout << typeid(buf_pool->watch).name() << "\n";
std::cout << (&buf_pool->watch[0] == buf_pool->watch) << "\n"; // prints 1
}
&buf_pool->watch[0] is the the address of the member 0 of watch contained in the struct buf_bool. Which is watch itself.
It is parsed like that because the whole buf_pool->watch[0] gets under the & (address of) sign.
You can check with this snippet:
#include <iostream>
#include <stdio.h>
using namespace std;
struct hello_t
{
int before;
int array[5];
};
int main() {
// your code goes here
struct hello_t hello;
hello.array[0] = 100;
struct hello_t* ptr_hello;
ptr_hello = &hello;
printf("ptr_hello = %X\n", ptr_hello);
printf("&ptr_hello = %X\n", &ptr_hello);
printf("&ptr_hello->before = %X\n", &ptr_hello->before);
printf("&ptr_hello->array[0] = %X\n", &ptr_hello->array[0]);
printf("");
return 0;
}
https://ideone.com/fwDnoz

Why do C++ function objects need reference type member variables?

This is a newbie C++ question. I was reading the "Function object" article in Wikipedia. The article has an example in C++ similar to the following:
struct printClass {
int &count;
printClass(int &n) : count(n) {}
void operator()(int &i) const {
count++;
cout << i << "[" << count << "] ";
}
};
int main(int argc, char** argv) {
vector<int> a(5, 7);
a[4] = -1;
a.resize(10, 3);
int state = 0;
for_each(a.rbegin(), a.rend(), printClass(state));
}
I have 2 questions:
Why does it fail to compile when count is a regular variable not a reference type? Demo
Why does it fail to compile it I change the ctor to the following? Demo
printClass(int &n) { count = n; }
Thanks.
EDIT: Thanks for explaining. I see that the following version works, too. Is there a reason for chosing one over another?
struct printClass {
int count;
printClass(int n) { count = n; }
void operator()(int &i) {
count++;
cout << i << "[" << count << "] ";
}
};
EDIT: Based on iammilind's reply, here is the 3rd version that works too using const_cast<int &>.
struct printClass {
int count ;
printClass(int n) : count(n) {}
void operator()(int &i) const {
const_cast<int &>(count)++;
cout << i << "[" << count << "] ";
}
};
(1) Why does it fail to compile when count is a regular variable not a
reference type?
This is a very interesting question. The question should be rather, why the code compiles when count is declared as a reference. :)
The regular variable fails because int count is not modifiable inside a const qualified function operator()(int &i) const;.
References are little different. In your code you are declaring the method as const, which means that count which is referring to i, now cannot refer to anything else.
But that's anyway not possible due to nature of references :). One cannot change reference binding after the initialization.
operator() just checks whether you are changing the binding of count to anything else or not? And the answer is always no. Because count++ changes the value referred by count and not the binding.
In your code, it doesn't matter if a member method is const or not when it comes to int& count.
Relate int& count; to int* const p_count; and try to simulate the situation on your own.
(2) Why does it fail to compile it I change the ctor to the following?
CountFrom(int &n) { count = n; }
Because reference must be assigned to a variable while initialization. In simple example;
int i, &r; // error, because 'r' not initialized
r = i; // this is not initialization but a copy
On a side note, you should be extra careful when you are dealing with reference variables inside a class. Because it's easy to mess up with their scope and validity.
For example, here the validity of count is dependent on the scope of i.
Edit: After your 2nd edit, it's very trivial to know why that version works.
Because count is now a simple variable. It can be skipped from initialization in the initializer list of the constructor unlike reference.
Moreover the const correctness of the operator() is gone, so any member variable of the class can now be modified inside it.
You should choose a const version of the member method, if you want to state that no class member "must" change inside it (unless any variable is mutable or you use const_cast). In all other cases use the normal version of the member method. They both can co-exist as well depending on your business logic. This is a bit of a broad question and it's worth to have another thread for this.

C++ Pointers help?

I need a little bit of help with using pointers in C++. Sorry to seem beginner but I really can't quite understand them. I have read the tutorial on pointers on the cplusplus.com website, so please don't suggest that.
I basically have a variable which holds the name of another variable, and I wish to access that variable through the holder one. I believe I need to use pointers, correct me if I'm wrong though.
E.g.
int a;
string b;
a = 10;
b = "a";
I need to access the variable "a" through the contents of variable "b".
Just to put this into better perspective, this is how I am using it:
int a;
a = 20;
void getVar(string name) {
cout << name;
}
getVar("a");
But as you can see, on the fifth line, that will just cout the value of name, in this case "a", but I want it to cout the value of the variable which name contains, so I want it to output "20".
Any help here would be much appreciated.
If you need to associate a name with a value, consider associative arrays otherwise known as dictionaries and maps. The Standard Template Library has std::map that you can use to associate text with a value:
#include <map>
#include <string>
std::map<std::string, int> my_map;
my_map["A"] = 20;
cout << my_map["A"] << endl;
What you are thinking of is called (Reflection) which C++ does not support. You can however use pointers to access what is in a variable it points to:
int a = 5; //int variable that stores 5
int *b = &a; //int pointer that stores address of a
(*b) = 10; //stores 10 into address that b points to (a)
cout << a; //prints 10
What you are trying to achieve is not possible in a compiled language (not considering reflection). You might accomplish something similar using a map data structure.
theMap["a"] = 20;
and a corresponding
void getVar(string key){
cout << theMap[key];
}
that can be called with
getVar("a");
Note that in this extremely simple sample theMap has to be in scope for the function, like in a class or a namespace.
If you use pointers you are just using a level of indirection not at all suited for your example. See Chads answer for instance.
Theres no real way for you to access variables by name like that unless you create some kind of container class that has a name member that you look up by. I'm not sure what this has to do with pointers though.
What you're asking for is called "reflection" or "introspection" - the ability to use design-time names for your program's objects (classes, variables, functions, etc) in run time. C++ does not support that out of the box - the design-time names are stripped upon compilation.
There are some libraries that provide that capability in C++; but there are also languages where reflection is is part of the language. Python or JavaScript, for example.
Maybe this could suit you:
int a = 5;
class b {
public:
b(int &x) { ref_ = x; }
int operator()(void) { return ref_; }
private:
int &ref_;
}
b my_b(a);
my_b() /* -> 5 */;
Your code does not use pointers. you're trying to convert a string into an identifier and print it's result, I don't know whether that's possible or not. If you intended using pointer your code should've looked like this:
int a = 20;
int* b = &a;
cout << *b;
quick fix for outputting integers only:
int a;
a = 20;
void getVar(int name) {
cout << name;
}
getVar(a);
If you need the function to work for any type of variable, maybe think about some template function.
Edit: Here is the code for the template program:
#include <iostream>
#include <string>
using namespace std;
template <class T>
void getVar(T name){
cout<<name<<endl;
}
int main()
{
string x="hee";
int y=10;
getVar(x);//outputs hee
getVar(y);//outputs 10
return 0;
}