Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Deep Dish Fuckfest
Sep 6, 2006

Advanced
Computer Touching


Toilet Rascal

That Turkey Story posted:

Think about it like this. An instance of B has certain invariants. Inheritance here is non-virtual meaning that B knows it has its own base A and may rely on that fact to be certain its invariants aren't violated. An instance of D also has certain invariants, but inherits virtually from A. In E, we can't make the assumption that giving access to B's base A from D will not inadvertently allow D to violate B's invariants (or even vice-versa). If B inherited virtually from A, you'd be forming a contract that says "I know that other people share this base and that is okay". Without that virtual, E shouldn't allow D to point into B's A.

Ah, yeah, it's pretty obvious when looked at it that way. I was looking at it purely from a "would the mechanism used to implement this break in that case" point of view. Truth be told, the reason I started wondering about this is that a few days ago I realized that I'd never really used virtual inheritance much, and that I had no goddamn idea how to use it beyond the typical "deadly diamond" pattern you see everywhere in books and examples. So I decided I'd just figure it out given the mechanism used by the compiler and see if it broke.

It never occurred to me it would be bad software engineering.

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Initialization order would also be really weird. Virtual bases obviously have to be constructed before any class that has that virtual base. As it stands, you get this nice phase distinction where you initialize all the virtual bases in the complete object, then initialize the normal hierarchy. If you could unique virtual bases with non-virtual bases, that first phase would leave the non-virtual hierarchy partially initialized, and you'd have to be able to tell arbitrary constructors not to initialize certain of their base classes. That's a *huge* increase in complexity.

raminasi
Jan 25, 2005

a last drink with no ice
Is there any way for me to give an anonymous-namespaced function access to private class members?

More generally, how do I create implementation helper functions for classes without cluttering up my header files?

nielsm
Jun 1, 2009



Bunch of options, maybe I'm missing something.

1. Let your header just define a pure abstract class (i.e. an interface), and implement the interface in your source files. Also have the header declare a factory function or class of a kind.

2. Forward-declare a class that will hold the implementation details, and let your public class hold a private pointer to that helper class.

3. Forward declare a class that will hold the implementation details, as just static methods. (A class used as a namespace.) Declare the actual class to have the implementation class as friend. I'm not sure if this is possible.

I think the first is the "purest" regarding OOP theory. The second is rather ugly.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

GrumpyDoctor posted:

Is there any way for me to give an anonymous-namespaced function access to private class members?
Pass the members as arguments to the functions.

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe

GrumpyDoctor posted:

Is there any way for me to give an anonymous-namespaced function access to private class members?

More generally, how do I create implementation helper functions for classes without cluttering up my header files?

If you're classes are getting too big and cluttered, you might have some luck by splitting off functionality/data into sub classes.

That Turkey Story
Mar 30, 2003

GrumpyDoctor posted:

More generally, how do I create implementation helper functions for classes without cluttering up my header files?

Sadly, Mustach's answer is pretty much the best you can do, or if you want to take it a step further to avoid passing a bunch of separate parameters:

code:
// Inside a header:
class your_type
{
public:
  void foo();
  struct data_members_t
  {
    // blah, blah, blah
  };
private:
  data_members_t data_members;
};
//////////////
// Inside an implementation file:
namespace {
void your_implementation_function( your_type::data_members_t& )
{
  // blah, blah, blah
}
}

void your_type::foo()
{
  your_implementation_function( data_members );
}
Yeah, it still sucks, I know.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
There's also this.

code:
// widget.h
class widget {
  friend class widgetimpl;
  int x;
  // etc.
};

...

// widget.cpp:
class widgetimpl {
public:
  // consider slapping __attribute__((always_inline)) on these
  static int &x(widget &w) { return w.x; }
  // etc.
};

static void helper(widget &w) {
  widgetimpl::x(w) += 5;
}
Obviously this is a giant encapsulation hole for anyone who wants to take advantage of it, but it does prevent accidental violations while letting you organize your implementation with as many static functions as you like.

raminasi
Jan 25, 2005

a last drink with no ice
:barf: Well, thanks for all these suggestions, but I don't think any of them are more attractive than just sucking it up and using a handful of private functions.

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe
Is there anything that can cause the Visual Studio debugger to mysteriously stop being able to display what a struct holds? I can see the address of the struct but I don't have the nice + to expand it any more.

It's just a simple struct like:

code:
struct Star
{
       int x;
       int y;
       int z;
}
I allocate memory for a bunch, the contents are there but the debugger can't pull it up and it's annoying. Something like Star stars[32]; works, Star* stars = (Star*)malloc(gently caress); doesn't.

:wtf:

slovach fucked around with this message at 07:49 on Feb 26, 2011

SimpleCoax
Aug 7, 2003

TV is the thing this year.
Hair Elf
I am writing a scientific simulation. I am dealing with a handful of 2D arrays I am using for a grid that I want to scale to a very large size (think 40,000^2 elements, but really as large as possible given available hardware). The thing I have going for me is that they will be sparse a lot of the time, meaning a lot of the entries most of the time will be constant until information propagates through the grid. What I want to do is only store and iterate through elements that are changing/contributing. I am comfortable finding which elements are not changing and skipping over them, but my problem is really with the memory allocation. I have heard of mmap, but I want to be able to tell the system to deallocate elements as well once they stabilize to constant values again. I know there are great libraries for sparse matrices available, but I don't think they really do what I would like. I really just want to be able to iterate through the grid like a 2D array, but be able to tell the system to allocate memory for certain elements or deallocate memory for certain elements. I use C, but something like a quadruply linked list isn't out of the question if I need to move to C++ to implement it. I feel like there has to be a nice way to make my grid smarter about memory; hash tables or something. I just can't find any good information about this, but I'm sure people have done what I would like to do, if I'm not using the right search terms or whatever. Speed is obviously a factor, but I'm way more concerned about shrinking memory requirements at the moment. Sorry this got so long, but I'm at the point where I'm looking anywhere for ideas on this and it's somewhat specific I guess.

Scaevolus
Apr 16, 2007

Unless you're reading/writing the matrix to the disk (a lot), you probably don't want to use mmap.

Quadtrees might be useful for implementing sparse grids.

Gerblyn
Apr 4, 2007

"TO BATTLE!"
Fun Shoe
What if you split up your data space into fixed size nodes, say 128x128 cells each. So you could represent a 65536x65536 grid with a 512x512 2D array of pointers to nodes. In each node you store a 2D array of cells, plus a counter storing how many of those cells contain data. As you write data into system, you can use that counter to figure out when it's safe to deallocate a node.

So, if you're empty value was 0.0f, you could use something like this:

code:

// By using a power of 2 size we can do bit shift/mask operations
// for faster calculations...
const int cCellSize=128;
const int cCellShift=7;
const int cCellMask=0x7f;

struct Node
{
  // Cell data
  float mData[cCellSize][cCellSize];
  // Number of cells that don't store a zero
  int mNumUsedCells;

  Node()
  {
    ZeroMemory(this,sizeof(Node));
  }
};

class NodeMap
{
public:
  // Allocate a map to store width/height cells of data
  NodeMap(int pWidth, int pHeight)
  {
    // Calculate how many nodes we need to store the data
    mNodeWidth=(pWidth+cCellSize-1) >> cCellShift;
    mNodeHeight=(pHeight+cCellSize-1) >> cCellShift;

    // Allocate an array to store the pointers to the nodes and zero it
    mNodes=new Node[mNodeWidth*mNodeHeight];
    ZeroMemory(mNodes,mNodeWidth*mNodeHeight*sizeof(Node));
  }

  // Write a value into cell pX, pY
  void WriteToCell(int pX, int pY, float pValue)
  {
    int index, nodeX, nodeY;
    CalculateNodeOffsets(pX,pY,index,nodeX,nodeY);
    
    if (pValue!=0.0f)
    {
      // Allocate a node if we don't have one
      if (mNodes[index]==NULL)
      {
        mNodes[index]=new Node;
      }

      // Check if an unused cell is now becoming used
      if (mNodes[index]->mData[nodeX][nodeY]==0.0f)
        mNodes[index]->mNumUsedCells++;

      mNodes[index]->mData[nodeX][nodeY]=pValue;
    }
    else
    {
      if (mNodes[index]!=NULL)
      {
        // Checked if a used cell is becoming unused
        if (mNodes[index]->mData[nodeX][nodeY]!=0.0f)
        {
          mNodes[index].mNumUsedCells--;

          // If we no longer are using any cells in the node, we can release it
          if (mNodes[index]->mNumUsedCells==0)
          {
            delete mNodes[index];
            mNodes[index]=NULL;
          }
          else
          {
            mNodes[index]->mData[nodeX][nodeY]=0.0f;
          }
        }
      }
    }
  }

  // Read a value from cell pX,pY
  float ReadFromCell(int pX, int pY)
  {
    int index, nodeX, nodeY;
    CalculateNodeOffsets(pX,pY,index,nodeX,nodeY);
    
    // If we don't have a node for the cell, then it must contain 0
    if (mNodes[index]==NULL)
    {
      return 0.0f;
    }
    else
    {
      return mNodes[index]->mData[nodeX][nodeY];
    }
  }

private:

  // Given a cell position, calculate the index of the node that stores that cell
  // and the offsets into that node's data array
  void CalculateNodeOffsets(int pX, int pY, int &pNodeIndex, int &pNodeX, int &pNodeY)
  {
    int nodeSpaceX=pX >> cCellShift;
    int nodeSpaceY=pY >> cCellShift;
    pNodeIndex=(nodeSpaceY*mNodeWidth) + nodeSpaceX;

    pNodeX=pX & cCellMask;
    pNodeY=pY & cCellMask;
  }

  // Buffer to store node data
  Node* mNodes;

  // Width/Height of the map, in nodes
  int mNodeWidth, mNodeHeight;
};

If you're data set is really sparse, then you could use a Quad Tree of nodes instead of a flat grid, which would be slower, but would use up less memory.

(This is just off the top of my head, by the way, I've never done what you describe and there may be much better ways.)

Caveat: I haven't compiled/tested the code above, so be warned about that. I really need to install a compiler on my home PC...

Edit: For example, I might have done all my bitshifts backwards v:shobon:v (now fixed)

Gerblyn fucked around with this message at 11:16 on Feb 26, 2011

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

slovach posted:

I allocate memory for a bunch, the contents are there but the debugger can't pull it up and it's annoying. Something like Star stars[32]; works, Star* stars = (Star*)malloc(gently caress); doesn't.
I think you're saying the malloced version will show stars[0]'s x,y,z but not stars[1]'s etc. right?
That's because a pointer doesn't know how big an array what it's pointing to is. You can debug-view further entries manually, by typing stars[1] into the viewer, and you might be able to cast it to a stars[32] in the debugger possibly though I haven't tried that.

litghost
May 26, 2004
Builder

roomforthetuna posted:

I think you're saying the malloced version will show stars[0]'s x,y,z but not stars[1]'s etc. right?
That's because a pointer doesn't know how big an array what it's pointing to is. You can debug-view further entries manually, by typing stars[1] into the viewer, and you might be able to cast it to a stars[32] in the debugger possibly though I haven't tried that.

You can hint the VS debugger with ",<#>". So in the watch "stars,32" will be treated as Star[32] instead of Star[1].

Goreld
May 8, 2002

"Identity Crisis" MurdererWild Guess Bizarro #1Bizarro"Me am first one I suspect!"

Gerblyn posted:

What if you split up your data space into fixed size nodes, say 128x128 cells each. So you could represent a 65536x65536 grid with a 512x512 2D array of pointers to nodes. In each node you store a 2D array of cells, plus a counter storing how many of those cells contain data. As you write data into system, you can use that counter to figure out when it's safe to deallocate a node.



A simple multiresolution approach like that really depends on the underlying data. The same even goes for a quadtree.

When dealing with a huge sparse matrix, it's important to know what exactly you're storing in it. For example, if you're encoding a geometric object and the matrix is just a big tensor that creates laplacians when multiplied by your points (ie. each row contains weight values for a vertex and its neighbors), then a space-partitioning method will still suck up a shitload of memory. In that case you're best off just storing the position of each of these in a simple array of lists (a list for each row), and having specialized matrix operations that deal with sparse rows and columns.

It might take longer but you'll likely have an order of magnitude less memory usage. I've found that for a lot of the applications that require huge sparse matrices like deformations of large meshes, you'll run out of memory really really loving fast if you're not careful.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

SimpleCoax posted:

I am writing a scientific simulation. I am dealing with a handful of 2D arrays I am using for a grid that I want to scale to a very large size (think 40,000^2 elements, but really as large as possible given available hardware). The thing I have going for me is that they will be sparse a lot of the time, meaning a lot of the entries most of the time will be constant until information propagates through the grid.
If I'm understanding this correctly, what you want is an mmap for the rarely-used elements, to keep the memory-use low, and something else with sparse contents for the in-use elements, to keep disk-thrashing low and speed high?

You could probably just use a std::map indexed on coordinates for the sparse in-use table, with some sort of "last used" value thrown in there for when to drop it out of the std::map and back to the mmap. The quad tree approach suggested by others might be better if elements frequently start accessing previously-unused elements nearby. std::map is designed for reasonably fast access to sparse data, though, and a little bit of time spend picking up 'idle' elements from the disk wouldn't be too bad.

So your "Get(x,y)" function would be approximately:
code:
iterator elementfind=Map.find(coord(x,y));
if (elementfind==Map.end()) {
 Mapentry *entry=&mmapdata[y*width+x];
 pair<std::map<coord,Mapentry>::iterator,bool> insertret;
 insertret=Map.insert(coord(x,y),*entry);
 elementfind=insertret.first;
}
return elementfind;
Then you'd just need to occasionally iterate through the whole map checking last-used values and copying and removing any old ones you find back into the mmapdata (being careful not to remove in the wrong way while you're still iterating on that entry). Or you could cross-index separately for expiring things, which would have the advantage of being quicker and not needing to worry about breaking a running iterator (you'd always just be going from the 'begin()'), but the disadvantage of more memory used and another thing you have to keep synchronised.

roomforthetuna fucked around with this message at 20:58 on Feb 26, 2011

SimpleCoax
Aug 7, 2003

TV is the thing this year.
Hair Elf
Wow, thanks for the replies gentlemen, and the coded effort Gerblyn. I truly appreciate the help. I'm still trying to absorb these ideas. I am also fine with just being given terms or ideas I should be searching for if anyone else has thoughts on it. I would really like to start off with established methods if I can, as I will be scaling this up with MPI after I (hopefully) shrink the iterations and memory requirements. I just feel like they should be out there, but I'm too dumb to find them. To anyone familiar, I'm just trying to avoid the complexity of implementing adaptive mesh refinement, which would be my ideal choice. I want my grid to adapt over time, but my element sizes can stay static at the moment. I also want to be clear that I don't need to do any matrix operations. I just have a 2D grid, that's 16 variables deep. So I need 128 bytes per element. I feel like it would end up being some sort of list of elements that are structs. Then I would have an extra grid (just some tiny data type) that's either 0 or 1 at each element stating whether or not the element needs memory or it's constant and whether I should do the calculations required for them, or skip them if they will have no effect on their neighbors. It's a hyperbolic wave equation type simulation, so meaningful data will be dense and grow from a certain location, and I will also need to access the neighbors of each element with little effort.

FearIt
Mar 11, 2007
I'm trying to debug a method that refuses to return.
I've placed cout's and also used the debugger to verify that the final return statement is being reached, but then nothing ever happens and the program hangs.
What could cause this sort of thing to happen?

Googling the problem hints that somewhere the call stack might be getting currupted.
If this ends up being the case, how can this be debugged, would the curruption have to occur somewhere in the current function, or could it have happened anywhere. (Single threaded)

Thank you in advance CoC

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
It could happen in any frame after the call, but is most likely in the immediately-called function or something it tail-calls.

valgrind is usually a good first pass for memory bugs, but it's got inherent limitations with the stack.

If you have a breakpoint immediately before a return that doesn't seem to return, I suggest looking at the stack to see if something's overwritten the return address and, if so, what data it was overwritten with. Often that's a pretty big hint as to what piece of code did the write. An alternative is to use a "step instruction" command, if your debugger has one; in gdb this is "stepi". In all cases, you'll need a pretty sophisticated understanding of call frames and the stack before it makes much sense.

nielsm
Jun 1, 2009



You may be able to set a breakpoint at the entry to the function and then set a data breakpoint on the return address on the stack.

That Turkey Story
Mar 30, 2003

Do you have any objects in scope with a non-trivial destructor?

slovach
Oct 6, 2005
Lennie Fuckin' Briscoe

roomforthetuna posted:

I think you're saying the malloced version will show stars[0]'s x,y,z but not stars[1]'s etc. right?
That's because a pointer doesn't know how big an array what it's pointing to is. You can debug-view further entries manually, by typing stars[1] into the viewer, and you might be able to cast it to a stars[32] in the debugger possibly though I haven't tried that.

No, it doesn't show anything. Not a single thing. Just the address of the malloc'd struct and thats it, no values.

roomforthetuna
Mar 22, 2005

I don't need to know anything about virii! My CUSTOM PROGRAM keeps me protected! It's not like they'll try to come in through the Internet or something!

slovach posted:

No, it doesn't show anything. Not a single thing. Just the address of the malloc'd struct and thats it, no values.
Oh. That's pretty weird. And the variable containing that pointer, at the point in the code at which you're debugging, is definitely of type Star* (or whatever), not accidentally a void* or anything? Have you tried looking at the same variable with the debugger's QuickWatch at the same place? If that has the same unhelpful result, try putting "(Star*)stars" in QuickWatch?

A MIRACLE
Sep 17, 2007

All right. It's Saturday night; I have no date, a two-liter bottle of Shasta and my all-Rush mix-tape... Let's rock.

code:
    string flag = "full_name";
    if (argc == 3) 
    {
        if (argv[2] == "1")
            //sort by full name
            flag = "full_name";
        if (argv[2] == "2")
            //sort by last name
            flag = "last_name";
        if (argv[2] == "3")
            //sort by ssn
            flag = "ssn";
    }
Can someone tell me why my flag isn't getting set here? Am I not parsing the command line arguments correctly? Already confirmed the conditional requirements are met in gdb.

Vanadium
Jan 8, 2005

The elements of argv and string literals both evaluate to char pointers so == will check whether they point at the same location. Since they only point at distinct locations with potentially equal contents, they will never compare equal.

Use strcmp(argv[2], "1") == 0 instead of argv[2] == "1", etc.

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
I'm looking for something in C++ that using info in an array, I can write that data to an image (well, write the info of multiple arrays to multiple images), but I can't seem to figure out pngWriter (it crashes with a segmentation fault when I use image.close() giving me some error to do with libpng.dll).

I'm basically questioning whether or not what I want can even be done in C++ and should I just look at a different language at this point as after a couple hours of trying to figure this out, I'm out of ideas how to get this to work.

edit:
After more work, I've got the code:
code:
	pngwriter image(1, 1, 0, "out.png");
	string filename = "too-new.png";
	image.readfromfile(filename.c_str());
	image.close();
It throws a segmentation fault without even giving me a line this time.

I'm using Code::Blocks 10.5 on Windows 7 if that makes any difference. I've linked up zlib, libpng, freetype up so I don't think there's a problem there, though there might be an issue with libpng as I dunno, I have the wrong version of the .dll file or something, but I'm unsure how I'd check this.

Master_Odin fucked around with this message at 02:45 on Mar 1, 2011

Scinon
Jul 23, 2006
Now with 2% more atoms!

Master_Odin posted:

edit:
After more work, I've got the code:
code:
	pngwriter image(1, 1, 0, "out.png");
	string filename = "too-new.png";
	image.readfromfile(filename.c_str());
	image.close();
It throws a segmentation fault without even giving me a line this time.


What line is throwing the fault? Use a breakpoint if you need to find it. Are you sure that the file "too-new.png" exists and is in the correct place? Does image actually have data in it when close() is called?

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies

Scinon posted:

What line is throwing the fault? Use a breakpoint if you need to find it. Are you sure that the file "too-new.png" exists and is in the correct place? Does image actually have data in it when close() is called?
After tracing it through, it gets to this line within pngwriter.cpp and then throws the segfault:
if (png_sig_cmp( (png_bytep) sig, (png_size_t)0, PNG_BYTES_TO_CHECK)

Of course, when setting up the check for just libpng, using
code:
	FILE *fp;
   unsigned char buf[PNG_BYTES_TO_CHECK];
	string file_name = "too-new.png";
   /* Open the prospective PNG file. */
   if ((fp = fopen(file_name.c_str(), "rb")) == NULL)
      cout << "err2...";

   /* Read in some of the signature bytes */
   if (fread(buf, 1, 4, fp) != 4)
      cout << "err1...";

   /* Compare the first PNG_BYTES_TO_CHECK bytes of the signature.
      Return nonzero (true) if they match */

   if(!png_sig_cmp(buf, 0, 4))
   {
   	cout << "we have PNG?";
   }
	fclose(fp);
It just gives me "libpng warning: Only compression windows >= 256 supported by PNG". Using this library is apparently too advanced for me or something as I just don't get it. It doesn't actually return true so I guess the segmentation fault error is being thrown due to the fact we don't have a PNG, but I have no idea why that is as the file does exist in the root of my project and it does exist.

Rahtas
Oct 22, 2010

RABBIT TROOP FOREVER!
Okay, so as I'm assuming is the usual in this thread, I'm new to C++. I chose it as my first language to attempt a project in because I played with it a little tiny bit in college (think "Hello World") before I joined the military; it seemed a good point to get back to programming since I at least know how to double click it's .exe.

I'm trying to create an inventory program for checking tools in and out. Part of the program will be to amend or remove things from an inventory list (which is one giant step I haven't gotten to yet - trying to get the easy things done first). Part of that is a username / password dealio so that just anybody can't go in and add or remove tools.

I found this bit o' code http://www.dreamincode.net/code/snippet554.htm that I'm trying to adapt to my causes, but when I simply copy and paste that code into a new project I get an error on my 'cin's.

Under all my >>'s I get an "error: no operator ">>" matches these operands". I don't know why and from what I can tell and my little bit of research on file i/o it should work. But it doesn't work. I'd really like to figure out why because that bit of code seems like a good jumping off point for password / username (and general) file referencing.

HFX
Nov 29, 2004

Rahtas posted:

Okay, so as I'm assuming is the usual in this thread, I'm new to C++. I chose it as my first language to attempt a project in because I played with it a little tiny bit in college (think "Hello World") before I joined the military; it seemed a good point to get back to programming since I at least know how to double click it's .exe.

I'm trying to create an inventory program for checking tools in and out. Part of the program will be to amend or remove things from an inventory list (which is one giant step I haven't gotten to yet - trying to get the easy things done first). Part of that is a username / password dealio so that just anybody can't go in and add or remove tools.

I found this bit o' code http://www.dreamincode.net/code/snippet554.htm that I'm trying to adapt to my causes, but when I simply copy and paste that code into a new project I get an error on my 'cin's.

Under all my >>'s I get an "error: no operator ">>" matches these operands". I don't know why and from what I can tell and my little bit of research on file i/o it should work. But it doesn't work. I'd really like to figure out why because that bit of code seems like a good jumping off point for password / username (and general) file referencing.

The istream class (cin is a version of istream) doesn't define a >> for std::string. You need to use getline(cin, <stringname>) to read in the strings.

TasteMyHouse
Dec 21, 2006

HFX posted:

The istream class (cin is a version of istream) doesn't define a >> for std::string. You need to use getline(cin, <stringname>) to read in the strings.

you could also write your own overload!

limip
Oct 24, 2003

Rahtas posted:

Okay, so as I'm assuming is the usual in this thread, I'm new to C++. I chose it as my first language to attempt a project in because I played with it a little tiny bit in college (think "Hello World") before I joined the military; it seemed a good point to get back to programming since I at least know how to double click it's .exe.

I'm trying to create an inventory program for checking tools in and out. Part of the program will be to amend or remove things from an inventory list (which is one giant step I haven't gotten to yet - trying to get the easy things done first). Part of that is a username / password dealio so that just anybody can't go in and add or remove tools.

I found this bit o' code http://www.dreamincode.net/code/snippet554.htm that I'm trying to adapt to my causes, but when I simply copy and paste that code into a new project I get an error on my 'cin's.

Under all my >>'s I get an "error: no operator ">>" matches these operands". I don't know why and from what I can tell and my little bit of research on file i/o it should work. But it doesn't work. I'd really like to figure out why because that bit of code seems like a good jumping off point for password / username (and general) file referencing.

Make sure that you're including <string>. For MSVC at least, the class definition for std::basic_string is included by some other headers, but the overloaded operators, including >>, are only defined in string.

HFX
Nov 29, 2004

TasteMyHouse posted:

you could also write your own overload!

He could, but I wouldn't throw an almost newbie into extending the standard C++ library.

Edit: Changed from STL to standard lib in case it offended anyone.

HFX fucked around with this message at 19:11 on Mar 1, 2011

Your Computer
Oct 3, 2008




Grimey Drawer
I feel like this is an incredibly stupid question, but it's been on my mind for too long now to not ask; Will my tiny, crappy programs eventually eat up all my RAM because I'm not freeing up memory explicitly? I mean, reading about C/C++ you always hear about all these ways to both allocate and free memory, which I don't quite understand (having mostly used Java). Am I right that this is something I should be concerned about when using C/C++?

(I feel so :downs: for asking this..)

nielsm
Jun 1, 2009



If you allocate memory dynamically (with the new operator, for example) and don't free it, and run for any amount of time, then yes it will stay allocated and eventually you will run out of address space, or memory in really bad situations.
If you use auto-allocated objects (i.e. things not allocated with operator new, or other dynamic allocation functions) then those are released when they go out of scope.

This function will leak memory:
code:
void foo ()
{
  std::vector<int> *v = new std::vector<int>(1000);
}
This function will not leak:
code:
void bar()
{
  std::vector<int> v(1000);
}
With proper usage of RAII, memory management won't be a major headache, however. (But it still requires care in design.)

Your Computer
Oct 3, 2008




Grimey Drawer

nielsm posted:

With proper usage of RAII, memory management won't be a major headache, however. (But it still requires care in design.)

Thanks! :)
What about deconstructors? I've never understood that either (as far as I know, there's nothing like it it Java?)

TasteMyHouse
Dec 21, 2006

Your Computer posted:

Thanks! :)
What about deconstructors? I've never understood that either (as far as I know, there's nothing like it it Java?)

When an object is created, its constructor is called.

When an object is destroyed, its destructor is called.

When you're allocating on the stack, this means that an object's destructor is called when the object goes out of scope.

When you're dynamically allocating memory (e.g. through "new") then this means that the destructor will be called when you deallocate the object (e.g. through "delete")

If the object doesn't have any internal dynamic memory allocation, you don't need to write a destructor, as the compiler will automagically generate one that does what needs to be done.

e.g.
code:
class bar
{
  int q;
public:
  bar():q(5){}
};

class foo
{
    bar a;
    bar b;
    bar c;

public:
    foo(b):a(),b(),c() {}
};

int main()
{
while(true)
    {
    foo z;
    }
}   
no explicit destructor necessary. at the end of each iteration of the while loop, foo's default, compiler generated destructor will be called, and it will in turn call the default destructor of each member "bar" object, and memory will be deallocated properly.

however, if you do THIS, and dynamically allocate the member objects inside foo:
code:
class foo
{
    bar* a;
    bar* b;
    bar* c;

public:
    foo()
    {
    a=new bar();
    b=new bar();
    c=new bar();
    }
};

int main()
{
while(true)
    {
    foo z;
    }
}  
NOW at the end of the while loop when z goes out of scope, the default destructor for foo will be called, but it won't know to deallocate the dynamically allocated "bar" that is pointed to by a, b, and c, because C++ doesn't perform any kind of garbage collection or reference tracking by default and so it has no way of knowing if those internal objects are "done".

So, this program will loop, allocating three new bars every time and never deallocating them, and you'll quickly run out of memory. What you need to do is write your OWN destructor in the foo class, like...
code:
class foo
{
    bar* a;
    bar* b;
    bar* c;

public:
    foo()
    {
    a=new bar();
    b=new bar();
    c=new bar();
    }
    ~foo()
    {
    delete a;
    delete b;
    delete c;
    }
};
this way, whenever z goes out of scope, the destructor will be called and z will be properly cleaned up after.

A good rule of thumb for when you need a destructor is the rule of three

TasteMyHouse fucked around with this message at 21:11 on Mar 1, 2011

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

HFX posted:

The istream class (cin is a version of istream) doesn't define a >> for std::string.
The header <string> contains that operator >> definition.

edit: Whoah, beaten

Mustach fucked around with this message at 13:09 on Mar 2, 2011

Adbot
ADBOT LOVES YOU

Rahtas
Oct 22, 2010

RABBIT TROOP FOREVER!

limip posted:

Make sure that you're including <string>. For MSVC at least, the class definition for std::basic_string is included by some other headers, but the overloaded operators, including >>, are only defined in string.

Thanks! That made it stop vomiting errors on me.

TasteMyHouse posted:

you could also write your own overload!

I don't know if I should be cry, be angry, or just cock my head to the side like a dog that just heard a strange noise.


So here's my follow up problem -
from what I was able to tell from the code I linked (http://www.dreamincode.net/code/snippet554.htm), other then the person had to write it while driving a bus (based on the spelling), is that as long as someone were to enter a valid username from the list and a valid password it would allow someone in, regardless if a username / password combo corresponded to each other or not. I tried it and instead found the opposite, I can't get in at all. I made the .txt's as the site instructed and gave it a shot and I couldn't get in.
Seeing as how I don't have much faith in that code anymore (because a) it didn't work, and b) it seemed to do a couple other screwed up things (what was the point of int num? Just so that the while loop will run indefinitely even though the if statement won't let you in if you've tried more than 3 times?)) I'm willing to try suggestions to fix that code, but I honestly wouldn't mind leaving it alone and shunning it.
So is there another source I can look into for a simple username / password list?
A lot of the stuff I've found googling around on my own launches into things much beyond me or into code I can't get to work. I'm just looking for something that sounds simple in my mind: someone types in a username, the program looks at a.txt and finds the username, it then looks at the password directly beneath it and tells you if the password you've entered is right or wrong. In my mind these entries are all in one .txt file one right after another, but I acknowledge that doing it a different way may make it much easier in c++.

tl;dr - Got a recommendation for some simple password / username file i/o code and/or lesson I could peruse and modify to my own uses? Or can someone offer more guidance to make above linked code work properly?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply