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
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.

Jose Cuervo posted:

Is the following reasoning correct:
The code long int* *&lbLmaxVals tells the function readInData that lbLmaxVals is a reference to a pointer to a pointer to long int? Whereas before the code long int* *lbLmaxVals just told the function readInData that lbLmaxVals was just a pointer to a pointer to long int, and a copy was made of this pointer to a pointer to long int?
That's right.

Adbot
ADBOT LOVES YOU

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
I have an open-ended question, more of a design quandary than an actual programming question.

Here's the situation in short: I'm working for my university on a small digital audio program that'll serve in labs for a new digital audio synthesis course. Basically, I'm building a GUI around a homemade library that uses portaudio for low-level audio communication. Now the idea is to have this library be the only project students need to worry about, and just recompiling the DLL from should let them test their changes.

Part of these labs will be creating filters, which are handled by the library but for the moment there's only one demo filter. Students'll create their own. I'm trying to come up with a sort of abstract factory lookalike that'll let them create audio filters without having to modify the factory itself. So in other words, just writing up a new class that derives the base Filter class should make it available for creation and for lookup by the GUI.

The best compromise I have for the moment is a macro that defines the class and registers it to a static hash_map associating the class name to a static creator function calling its constructor. I'm not too fond of this approach, though, so I'm wondering if there's something smarter I could be using.

That Turkey Story
Mar 30, 2003

Jan posted:

The best compromise I have for the moment is a macro that defines the class and registers it to a static hash_map associating the class name to a static creator function calling its constructor. I'm not too fond of this approach, though, so I'm wondering if there's something smarter I could be using.

If I understand correctly, you want a way to have it automatically register and lookup the class by name so that they can call some factory function with a string and have it return an instance of the proper type? A macro might actually be your best option, but here's some code based on CRTP that works too.

code:
class your_base
{
  // Your virtual functions, etc.
};

// This is what you inherit from
template< typename ChildType, char const* const& Name >
class your_base_helper
  : public your_base
{
  struct child_registerer
  {
    child_registerer()
    {
      // Put code that registers the class here
    }
  };

  static child_registerer registration_object;
};

template< typename ChildType, char const* const& Name >
typename your_base_helper< ChildType, Name >::child_registerer
  your_base_helper< ChildType, Name >::registration_object;
Then, users who want to create plugins do:

code:
extern char const* const name_of_plugin;

class plugin
  : public your_base_helper< plugin, name_of_plugin >
{
  // define your functions
};
This way, simply creating a plugin type will imply automatically registering it.

Of course, they'd have to define "name_of_plugin" somewhere to be the name of the plugin used for lookup. boost::mpl::string would get rid of the need to do the extern char thing but I doubt you want to use that here. If you have a problem with having an intermediate public base, you can push it to a private, non-intermediate base so that it's entirely an implementation detail.

I think you may have to refer to the registration object somewhere for it to portably be instantiated regardless of your compiler -- if so, just refer to it in an empty constructor in the base_helper (since that will automatically be instantiated by the child type).

Edit: There are also other advantages of making it a non-intermediate base, I.E. it easily works for registering children of registered types, though you can do this with the current approach as well by making the base type of the helper template instantiations be a template parameter that just defaults to your_base. It's up to you whether you want to introduce private and multiple inheritance or not.

That Turkey Story fucked around with this message at 20:11 on Aug 24, 2010

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
Yeah, I figured something was possible to create at compile-time using templates but I'm not handy enough with template tricks to come up with something like that. Thanks, that'll give me a good alternative to consider.

Edit: So I haven't really managed to get even my macro solution down to self-containment. Self-referencing isn't working, MSVC refuses to initialise the static items unless they're referred to from somewhere else. I'm getting the same problem with that template solution.

Furthermore, it's not taking an extern char * as a valid template argument, it somehow still considers it as internal linkage. I can sort of cheat the whole idea by using typeid(ChildType).name() for registering but that name's compiler dependent and in the case of MSVC it gets some extra syntax I have to parse away.

It's starting to look like I'll just have to trust users to manually register their new plugins, ah well.

Jan fucked around with this message at 23:56 on Aug 24, 2010

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!
Just a little update - Google Breakpad sounded like just what I was looking for in crash-debugging, but it turns out it's recently been modified to make it a massive pain in the arse to get working in Windows, to the point that I'd now rather modify this guy's thing and add file-dumping, uploading and pdb cross-referencing myself. (Edit: on second thought, that basically leaves nothing of that guy's thing, so I might as well just write my own from scratch. It looks pretty easy now that I've found all the functions I need.)

It really should just be a case of "get exe, lib and headers" (the exe would be the uploader app), or "get source, build projects, use those exe, lib and headers", but instead there's a crazy song and dance required to even get the source and project files ready, and then when I finally managed that, the compilation failed, unable to find one of its own header files, having an undeclared variable, and a couple of buckets full of deprecated function warnings.

In summary, gently caress cross-platform open source libraries that are still in development and don't have a clear "latest stable version" option.

roomforthetuna fucked around with this message at 02:50 on Aug 25, 2010

kes
Jan 4, 2006

roomforthetuna posted:


It really should just be a case of "get exe, lib and headers" (the exe would be the uploader app), or "get source, build projects, use those exe, lib and headers", but instead there's a crazy song and dance required to even get the source and project files ready, and then when I finally managed that, the compilation failed, unable to find one of its own header files, having an undeclared variable, and a couple of buckets full of deprecated function warnings.

In summary, gently caress cross-platform open source libraries that are still in development and don't have a clear "latest stable version" option.


isnt this how every open source project works

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.

I'm getting a weird run-time error:

code:
terminate called after throwing an instance of 'std::length_error'
  what():  basic_string::_S_create
I'm trying to sort an array of a class of friends based on their score (an element of the class); I rearranged my sorting algorithm a little bit and it compiled but doesn't run correctly.

here is my sort:
code:
 //sort friends by score:
    for (int i = 0; i < (iterator - 1); i++){
        int newSmall = i;
        for (int j = i + 1; j <= iterator; j++){
            if (friendArray[j].score < friendArray[newSmall].score){
                newSmall = j;
            }
        }
        //swap lowest with current low index:
        friends tempFriend = friendArray[i];
        friendArray[i] = friendArray[newSmall];
        friendArray[newSmall] = tempFriend;
    }

iterator is the size of the array btw

Mr.Radar
Nov 5, 2005

You guys aren't going to believe this, but that guy is our games teacher.
In the second for loop I think the condition should be j < iterator rather than j <= iterator so that j doesn't go beyond the end of friendArray. The runtime error is probably caused by the std::string assignment operator or copy constructor trying to interpret random garbage past the end of the array as an std::string (in the friends assignment operator).

That said, I have a few questions about your code. Is friendArray a raw array or a container like an std::vector? If it's a raw array, do you have a good reason why? If it's a container, why are you iterating over it by index instead of with an iterator? Also, why are you rolling your own sorting routine instead of using std::sort with a custom comparator, and why did you choose selection sort instead of a faster algorithm?

Mr.Radar fucked around with this message at 22:29 on Aug 25, 2010

floWenoL
Oct 23, 2002

roomforthetuna posted:

(Edit: on second thought, that basically leaves nothing of that guy's thing, so I might as well just write my own from scratch. It looks pretty easy now that I've found all the functions I need.)

NIH syndrome strikes again!

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!

floWenoL posted:

NIH syndrome strikes again!
Hey, that's not fair, I was perfectly willing to use a third-party library that did what I wanted. It just sucked and turned out to be more work to get it working than making it myself would be.

NIH syndrome is "everyone else's stuff sucks so I'll do it all myself", this was "only this one library allegedly does what I want, and it, specifically, sucks."

(Admittedly I do feel that way almost every time I try to use a third-party library for anything, but it's not because I object to third-party things, it's just that I object to libraries that don't actually save me work!)

Vinterstum
Jul 30, 2003

roomforthetuna posted:

Hey, that's not fair, I was perfectly willing to use a third-party library that did what I wanted. It just sucked and turned out to be more work to get it working than making it myself would be.

It always looks that way, at first. That IS what the NIH syndrome is. Then you start implementing it yourself, and find out that halfway through you actually DID need that one feature that you thought was bullshit. And a few performance issues later discover that there WAS a good reason why this particular subsystem had that retarded way of doing things.

In the end, you'd have saved plenty of time and effort by going the 3rd party route in most cases. Unless you really only need a small part of the functionality offered, and the project is *truly* awful (and what you mention doesn't qualify).

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!
Well, I do only need a small part of the functionality (I don't need any of the cross-platform stuff, which potentially reduces the 'dump' part to a single API function call, for example), and I already need to deal with some HTTP stuff so I'd be better off uploading the dump file with my existing HTTP stuff than including a second one, which is also better when it comes to the server-side because I won't need to deal with integrating their server-side stuff (if there even is any in the library).

There certainly isn't a good reason (from a library-user perspective) why the library would be a pain in the arse to download and then not actually compile once downloaded. So I'm safe from the "there WAS a good reason for the retarded way of doing things" problem.

(I'm sure there is a good reason for it not compiling and having outdated documentation from an open-source developer perspective, such as "some fucker uploaded an update into the version control system that broke things and it didn't get fixed yet", but that doesn't make it worthwhile from the perspective of someone who wants to use the library.)

Edit: and it doesn't always look that way at first, I've been perfectly satisfied with eventlib (on the Linux side), libjpeg, libtomcrypt and zlib, for example, with no temptation to write my own.

roomforthetuna fucked around with this message at 04:16 on Aug 26, 2010

floWenoL
Oct 23, 2002

roomforthetuna posted:

There certainly isn't a good reason (from a library-user perspective) why the library would be a pain in the arse to download and then not actually compile once downloaded. So I'm safe from the "there WAS a good reason for the retarded way of doing things" problem.

(I'm sure there is a good reason for it not compiling and having outdated documentation from an open-source developer perspective, such as "some fucker uploaded an update into the version control system that broke things and it didn't get fixed yet", but that doesn't make it worthwhile from the perspective of someone who wants to use the library.)

There will be always some effort necessary to get third-party libraries working. That effort is almost always significantly smaller than the effort necessary to write your own; it just doesn't seem that way since writing code gives the appearance of progress whereas getting a third-party library working is something that doesn't work for a while until you get everything lined up correctly. Sorry, this is a pretty clear-cut case of NIH, especially since Breakpad is hardly some neglected half-baked Sourceforge project.

Dooey
Jun 30, 2009
I have a function that looks pretty much like this:

code:
void Image::traceColor(const Rgb toTrace, Point startPos) {
	std::stack<Point> pointStack;
	pointStack.push(startPos);
	while (!pointStack.empty()) {
		Point curPoint = pointStack.top();
		pointStack.pop();

		/*do stuff with curPoint*/

		if (*getPixelRgb(curPoint + Point(1,0)) > toTrace) {
			pointStack.push(curPoint + Point(1,0));
		} 
		if (*getPixelRgb(curPoint + Point(0,1)) > toTrace) {
			pointStack.push(curPoint + Point(0,1));
		} 
		if (*getPixelRgb(curPoint - Point(1,0)) > toTrace) {
			pointStack.push(curPoint - Point(1,0));
		}
		if (*getPixelRgb(curPoint - Point(0,1)) > toTrace) {
			pointStack.push(curPoint - Point(0,1));
		}
	}
}
What is does is take and image and a point on the image and highlight the area on that image at that point that is that color. Imagine the magic wand and bucket tool used right after each other and thats pretty much what this does. I'm pretty sure there is a name for this sort of algorithm, but I can't think of it right now. Depth First Search maybe. Anyway, the problem is this: the first time I ran the code, it had a typo, and looked like this:

code:
void Image::traceColor(const Rgb toTrace, Point startPos) {
	std::stack<Point> pointStack;
	pointStack.push(startPos);
	while (!pointStack.empty()) {
		Point curPoint = pointStack.top();
		pointStack.pop();

		/*do stuff*/

		if (*getPixelRgb(curPoint + Point(1,0)) > toTrace) {
			pointStack.push(curPoint + Point(1,0));
		} 
		if (*getPixelRgb(curPoint + Point(0,1)) > toTrace) {
			pointStack.push(curPoint + Point(0,1));
		} 
		if (*getPixelRgb(curPoint - Point(1,0)) > toTrace) {
			pointStack.push(curPoint - Point(1,0));
		}
		if (*getPixelRgb(startPos - Point(0,1)) > toTrace) {
			pointStack.push(curPoint - Point(0,1));
		}
	}
}
(note the usage of the wrong variable in the second to last line. startPos instead of curPoint)

and it worked great in the three cases without the typo, but in the fourth case, it would screw up, leaving an unhighlighted area anywhere where there was a sort of upside down cup in the image. I'm not sure if I'm explaining this well, so if this is hard to follow let me know and I'll try to clarify.

So, I changed it to the fixed version up above, but it ran way slower, changing my framerate (this is ran on a video feed) from 15 FPS to .5 FPS and I have no idea how this small change can affect my speed so much. My only idea is that the incorrect version provides for some amazing compiler optimization that the correct version cant do, but I have no ideas beyond that. Can anyone tell me what is going on? Or is there some way to test my theory that there is an optimization that is being performed on the second chunk of code but not the first?

I can provide more details if necessary. This is compiled using Visual Studio 2010 by the way.

Also I'm trying hard to avoid getting into any bad coding habits in this project, so if you see any, let me know, please :)

Also, a couple other miscellaneous unrelated questions: Is there any easy way to make a specialized version of a template class that is identical to the non specialized version except for one additional member function? Also, is it OK to throw exceptions inside constructors?

digibawb
Dec 15, 2004
got moo?
If you have performance problems, profile, don't guess.

The most obvious answer would be that you just end up with less entries being pushed into the stack => less work to do. Simple test would be to just log how many items you push onto the stack with both the right and wrong versions.

shrughes
Oct 11, 2008

(call/cc call/cc)
We can assume that /*do stuff with curPoint*/ is guaranteed to modify the image in-place at that point, so that the new RGB value is less than or equal to toTrace, right? Otherwise you're going to be revisiting points over and over again.

What the gently caress? How can you take an Rgb value and compare it for inequality to another Rgb value? That makes no sense whatsoever.

I'm pretty sure your problem is that you're revisiting a lot of points multiple times. There is something messed up with your reasoning, regarding this mystical Rgb comparison function and what side effect you're applying to the image.

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!

floWenoL posted:

There will be always some effort necessary to get third-party libraries working.
But there's a big difference between "some effort to get it working" and "it's actually broken at the moment". If it doesn't even compile then there's a good chance there's going to be runtime bugs too, especially when a library is still in active development. If there was a "last known stable" version (maybe there is - I should say if there was a last known stable version clearly marked as such and readily available) then I'd have put in more effort to get it to work, but fixing something that's actively broken in a library that there's a good chance you're also going to have to update to newer versions (that may also require fixing again) is not just "some effort to get it working".

And it's not really a case of "it seems better to do it yourself because you see progress" - it took me about 20 minutes to implement the main 'crash-dump' part in a way such that it applies throughout my project, and I expect similar for the 'upload' part when I get to it. I already spent longer than that trying to get Breakpad to compile.

If, after all this reasoning, it's still a case of NIH syndrome, then good, I guess.

vvvv Wasn't citing him as an authority or anything (I don't even know who it is), just a summary of the point that if it's still NIH syndrome when it actually is faster and easier and possibly more effective to write it yourself, then in those cases NIH syndrome is good. The alternative is that this wasn't a case of NIH syndrome. Unless you'd like to argue that slower, harder and worse is good.

roomforthetuna fucked around with this message at 17:17 on Aug 26, 2010

Vanadium
Jan 8, 2005

joel is, as a rule, wrong as gently caress

Dooey
Jun 30, 2009

shrughes posted:

We can assume that /*do stuff with curPoint*/ is guaranteed to modify the image in-place at that point, so that the new RGB value is less than or equal to toTrace, right?

Yep.

shrughes posted:

What the gently caress? How can you take an Rgb value and compare it for inequality to another Rgb value? That makes no sense whatsoever.

An Rgb is greater than another Rgb if each component is greater. It makes sense to me, and it makes sense in the program I'm writing. v:shobon:v

I'll do some profiling and see if I can figure anything out that way, thanks digibawb.

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.

roomforthetuna posted:

but fixing something that's actively broken in a library that there's a good chance you're also going to have to update to newer versions (that may also require fixing again) is not just "some effort to get it working".
It's an open source project; have you considered fixing it and submitting a patch? (Keep in mind that this is a question and not an accusation.)

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!

Mustach posted:

It's an open source project; have you considered fixing it and submitting a patch? (Keep in mind that this is a question and not an accusation.)
Briefly. But the point of using the library was to save me a little work on my project, not to suck me into a whole different project where I'd come in with no idea what anything does, spend days learning about it, and then eventually have my patch rejected because I didn't understand their peculiar cross-platform implementation/philosophy.

Also, the last time I tried looking into patching an open source project it was Firefox. That vomitpool of code has put me off ever doing anything with open-source code other than "compile it".

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Dooey posted:

My only idea is that the incorrect version provides for some amazing compiler optimization that the correct version cant do, but I have no ideas beyond that.

It is possible that the compiler was able to hoist part of the fourth check out of the loop. Since you do three other checks that clearly can't be hoisted, we can cap the speedup of this optimization at 25%. It is not responsible for the change in your performance.

shrughes is right, you're doing way more work than you used to, probably because points are reachable along multiple paths.

Dooey posted:

Also, a couple other miscellaneous unrelated questions: Is there any easy way to make a specialized version of a template class that is identical to the non specialized version except for one additional member function?

Give them a common template base class.

Dooey posted:

Also, is it OK to throw exceptions inside constructors?

Yes, although if you're going to use exceptions you need to use RAII smart pointers religiously. They're a good idea anyway, but it is literally impossible to get some cases right with try blocks, so smart pointers are mandatory.

Rocko Bonaparte
Mar 12, 2002

Every day is Friday!

roomforthetuna posted:

Also, the last time I tried looking into patching an open source project it was Firefox. That vomitpool of code has put me off ever doing anything with open-source code other than "compile it".

Firefox code is a terrible role model. It has a ton of kruft just from being around so long--having taken stuff from years and years and years ago. Doesn't it still have some code that's technically Netscape? That's not necessarily a problem with open-source so much as a problem of an old project.

Heck I think gentoo still gives you the option to install firefox as binaries since compiling it from an ebuild can be nontrivial.

Now if you want to get into reasons to stay away from open-source, being treated like an idiot is probably one common one right there, and I guess you have that in mind already when you try to submit a patch. Although what I find more often is it'll go in a big pile and just fart around there forever. I tried to contribute to Boost once and, well, who knows.

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.

Mr.Radar posted:

In the second for loop I think the condition should be j < iterator rather than j <= iterator so that j doesn't go beyond the end of friendArray. The runtime error is probably caused by the std::string assignment operator or copy constructor trying to interpret random garbage past the end of the array as an std::string (in the friends assignment operator).

That said, I have a few questions about your code. Is friendArray a raw array or a container like an std::vector? If it's a raw array, do you have a good reason why? If it's a container, why are you iterating over it by index instead of with an iterator? Also, why are you rolling your own sorting routine instead of using std::sort with a custom comparator, and why did you choose selection sort instead of a faster algorithm?

Thanks Mr.Radar, you helped me solve my problem. This is a "refresh your C++ skills" lab for my data structures class and the instructions were very specific about the types of algorithms I should employ.

Gangsta Lean
Dec 3, 2001

Calm, relaxed...what could be more fulfilling?
roomforthetuna, have you looked at bugtrap?

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!

Gangsta Lean posted:

roomforthetuna, have you looked at bugtrap?
I hadn't, and thanks for the recommendation - it looked really good until I got to the options for the delivery of crash reports, which appear to be too Windows- or Java-dependent for my setup (my server is all Linux and no Java). I also foresee a problem with crashes while in DirectX full screen mode trying to pop up a "do you want to report this error" dialog box - dialog boxes and DirectX full screen frequently not playing well together. Even then, it still looks pretty good, and well documented, and set up to be pretty easy to use. I am tempted. It's a big improvement over the terrible docs for Breakpad.

I acknowledge that this time I really am pulling an NIH syndrome - I want it done my way, and the pre-existing solutions just don't have quite enough options to make it that way.

(I'm planning on dumping the crash report to a file, triggering a separate "ask and send the report" program, then finishing the crash-out from the main program so DirectX will drop its greedy control of the screen. And for the sending, a simple HTTP file-send so I can just receive the report with any webserver and a tiny amount of script.)

Dooey
Jun 30, 2009

rjmccall posted:

It is possible that the compiler was able to hoist part of the fourth check out of the loop. Since you do three other checks that clearly can't be hoisted, we can cap the speedup of this optimization at 25%. It is not responsible for the change in your performance.

shrughes is right, you're doing way more work than you used to, probably because points are reachable along multiple paths.

I haven't worked with a profiler much, so I'm going to try that next when I have more than 10 minutes to play with it, but I did try counting the number of pushes into the stack since it only take 5 minutes to try, and the count for the correct version about twice the count for the incorrect version. Not enough to account for taking 20 times longer. I'll check it out with the profiler when I have some time to actually play with it (and when its not 2 in the morning)

Thanks for your answers to my other questions as well :)

Pesch
Nov 4, 2006
Wholly Chao
What exactly happens when you reassign a new object over a statically allocated object?

Does the destructor get called automatically on the old object before or after reassignment, or does the new object simply overwrite the old object and you should explicitly call the destructor if needed? Or is this behavior undefined?

Example:
code:
#include <string>
#include <iostream>
using namespace std;

class Test
{
    int n; 

    public:
        Test(int n)
        {
            this->n = n;
            cout << "Constructor " << n << endl;
        }

        ~Test()
        {
            cout << "Destructor " << n << endl;
        }
};

int main()
{
    Test t = Test(1);
    t = Test(2);
    t = Test(3);

    return 0;
}
I tried this with g++ and got:
code:
Constructor 1
Constructor 2
Destructor 2
Constructor 3
Destructor 3
Destructor 3

OddObserver
Apr 3, 2009
operator=. And you have some temporaries there.

Pesch
Nov 4, 2006
Wholly Chao

OddObserver posted:

operator=. And you have some temporaries there.

Is the behavior undefined without = overloaded?

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!
Longer version of OddObserver's explanation -
"Test t = Test(1)" could potentially go two ways - in this case it's being treated as identical to "Test t(1)", as an initialiser not an = operator. It could also be treated as identical to "Test t; t = Test(1);" which would require a constructor with no parameters to exist, and then would act more like the other lines.

So at this stage you've done basically "Test t(1)", t.n is 1, and the constructor has been called with 1, for that output.

"t = Test(2)" - this makes a temporary 'Test' object and then uses the = operator, which, not having been explicitly defined, I believe acts like "t.n = temporary.n" for every member variable. So you get constructor 2 and destructor 2 called for the temporary object, and t.n is now 2.

"t = Test(3)" - does the same thing, so you get constructor 3, destructor 3, and t.n is now 3.

Then you hit the return and go out of scope - t is destroyed, the destructor is called and outputs t.n, so you get your second "destructor 3".

Edit: Am I correct for what the default = operator does, such that member objects' overloaded = operators would be called, or does it just act like a memcpy? It's never really come up for me that I'd be using it and there'd be a difference.

roomforthetuna fucked around with this message at 02:24 on Aug 28, 2010

pseudorandom name
May 6, 2007

Member-wise assignment, although there's nothing stopping to from just doing a memcpy() if it can get away with it.

(Hooray for the "as-if" rule!)

Pesch
Nov 4, 2006
Wholly Chao
Does the default = operator return a copy of the object also?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

roomforthetuna posted:

"Test t = Test(1)" could potentially go two ways - in this case it's being treated as identical to "Test t(1)", as an initialiser not an = operator. It could also be treated as identical to "Test t; t = Test(1);" which would require a constructor with no parameters to exist, and then would act more like the other lines.

Most of your explanation is fine, but I wanted to point out that this is not quite right. Under the formal semantics, this statement proceeds in three steps. First, it initializes a temporary of type Test; since there's exactly one argument, this is analyzed as a type conversion, which here works out to involve a constructor call. Second, we copy-initialize the variable t by calling the copy constructor for Test, passing a reference to the temporary we just initialized. Finally, we destroy the temporary.

You might think that making the temporary here is silly, and you'd be right. And fortunately the standard agrees! So the compiler is allowed to elide this copy by initializing t in place in the same way that it was previously initializing the temporary. When this optimization is done — and it's done by pretty much every compiler — it's as if only the first step were performed.

But in no case will the variable end up being default-initialized with a follow-up call to the copy assignment operator.

It's worth pointing out that this *only* applies to an = that's part of the declaration of a variable. Every other = calls an assignment operator.

rjmccall fucked around with this message at 03:11 on Aug 28, 2010

Oisin
Jul 22, 2009
Are there any C sites with assignments in increasing difficulty? I know of Project Euler but I was hoping to code things on a bit of a larger scale.

shrughes
Oct 11, 2008

(call/cc call/cc)

Oisin posted:

Are there any C sites with assignments in increasing difficulty? I know of Project Euler but I was hoping to code things on a bit of a larger scale.

Sure, there's one in this thread.

1. Using C99, write a loop that won't terminate until after the heat death of the universe. Use no more than 60 characters. You can assume int rolls over.

2. Write an arena allocator.

3. Using C99, write a loop that won't terminate until after the heat death of the universe. Use no more than 50 characters. You can assume int rolls over.

4. Write a Scheme interpreter.

5. Add bigints to your Scheme interpreter using gmplib.

6. Write your own bigint implementation and use that instead.

7. Make a regular expression library.

8. Make a parser generator, like bison, except with less features.

9. Using C99, write a loop that won't terminate until after the heat death of the universe. Use no more than 40 characters. You can assume int rolls over.

10. Make an Scheme compiler that targets C99. Let some of the runtime still use C99.

11. Using epoll or the best equivalent, make a really fast HTTP proxy with tons of features that avoids copying data as much as possible.

Jose Cuervo
Aug 25, 2004
I am having a problem using vector. I want to store an number of allocations that I come across. An allocation is just a set of integers that is problem dependent. Because I do not know the number of allocation I will encounter, and the number of integers that are needed to represent an allocation, I chose to use a vector of vector of ints:
code:
#include <iostream>
#include <vector>

using namespace std;


int main() {

	vector <vector <int>> everyAllocSearched;

	for (int i=0; i<5; i++) {
		everyAllocSearched.push_back(vector <int>());
		for (int j=0; j<=10; j++)
			everyAllocSearched[i].push_back(i*j);
	}

	return 0;
}
My problem now is I do not know how to access the individual elements using iterators. Help please.

Jan
Feb 27, 2008

The disruptive powers of excessive national fecundity may have played a greater part in bursting the bonds of convention than either the power of ideas or the errors of autocracy.
Iterators aren't the easiest way to access vector values. Any reason you can't just use plain operator[]?

code:
	for (size_t i = 0; i < everyAllocSearched.size(); i++)
	{
		for (size_t j = 0; j < everyAllocSearched[i].size(); j++)
		{
			std::cout << everyAllocSearched[i][j] << std::endl;
		}
	}
If you must use iterators, then:
code:
	for (vector <vector <int>>::iterator it = everyAllocSearched.begin(); it != everyAllocSearched.end(); it++)
	{
		for (vector <int>::iterator jt = it->begin(); jt != it->end(); jt++)
		{
			std::cout << *jt << std::endl;
		}
	}
If you know your indices and still want to access a single element with iterators, then, exceptionally you can simply add to them since you're dealing with vectors and therefore are the proud owner of random_access_iterators:
code:
	vector <vector <int>>::iterator it = everyAllocSearched.begin() + 3;
	vector <int>::iterator jt = it->begin() + 6;
	int alloc3_6a = *jt;

	// More concisely
	int alloc3_6b = everyAllocSearched[3][6];
Edit: Note iterators can also use the subscript operator[] notation -- doing some_iterator[n] will effectively fetch the value "n" elements away from your iterator's position. For instance, this will do the same as the previous 2 examples:

code:
	int alloc3_6c = everyAllocSearched.begin()[3].begin()[6];

	// or even reusing the earlier jt:
	int alloc3_6d = jt[0];
Between all these different ways of accessing elements surely something ought to do what you want.

Jan fucked around with this message at 00:40 on Aug 30, 2010

Jose Cuervo
Aug 25, 2004

Jan posted:

Very helpful information.

The first way you posted is very helpful and is what I will end up using. The second way is what I was trying to do and could not make it work, but it is nice to see how to do it that way.

Appreciate the help.

Adbot
ADBOT LOVES YOU

Risible
Jun 1, 2009
I have a function that populates an element in a set I'm working with in C.

The set comes with a library of functions, one of which returns a pointer to the first element in the set on its first call; the function is called setIterate().

After I call this function, assign this pointer, and get ready to display its contents -- what it points to -- I use printf to display text to the screen. When printf is called the contents of memory the pointer is looking at gets changed, and I have no idea why. There should be no reason why printf() is changing it, but when I comment out the printf() statement the program appears to work fine.

What could printf() be doing to cause this change? I'm completely baffled.

(The source of the set that I'm using is here: http://www.mcternan.me.uk/MCS/ )

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