|
That's perfectly fine, the usual way of doing it is to create a temp object in the sort() call and pass the appropriate data to its ctor:
std::sort ( start, end, <font color=red>myCriteriaFunctor(true, 42)</font> ); If you need the object lifetime to be longer than just that one line, you can create it on the stack like any other C++ object. (A "functor" is a C++ object, after all, it just also has an overloaded operator() for STL to call.)
--Mike--
LINKS~! Ericahist updated! | 1ClickPicGrabber | CP SearchBar v2.0.2 | C++ Forum FAQ
Strange things are afoot at the U+004B U+20DD
|
|
|
|
|
Hi,
I'm a bit confused with the copy constructor business. A book I found says that given a variable 'a' of type MyClass, if you have:
<br />
a = SomeFunction();
then the copy constructor of MyClass would be invoked. None of the examples I've seen on the net ever try to delete memory inside a copy constructor. They only allocate new memory and copy the stuff. However in this case 'a', would already exist with some memory being used and would result in a memory leak? If the book is wrong and the operator=() is called then that makes more sense. Or possibly most of the examples I've seen are wrong and you should always call delete on your memory in the copy constructor.
Thanks for cleaning this up. If you know of a good resource on the net on this topic let me know.
|
|
|
|
|
Hi friend,
I don't know what kind of book you read, but i think that you might missunderdstood the issue.
In the example you wrote:
a = SomeFunction(); //returns MyClass object
You are right, the operator= is called, but have you read the implementation of operator=...?
if you are using a default version of operator=, then you will get a call of the copy construcor because its implemntation goes like this:
<br />
M operator=(const M &m)<br />
{<br />
return m;
}
because a copy of object m is returned BY VALUE, not the actual object will be returned, but a copy of object m. No memory leak will occur because this temporary object is created on the stack!
Furthermore, if you create an object with the operator=, the copy constructor will be called instaed of operator=
MyClass new=old; //copy constructor is called.
A good resource is the book Thinking in C++ version 2, it is available on many sites for FREE. use a search engine to find it.
Good luck,
Mohammad Gdeisat
|
|
|
|
|
Well, the default assignment operator generated by the compiler will *NOT* result in a copy constructor call. It does a bitwise copy and that's the source of the dangling pointer problem.
And if you define your own operator =, you're supposed to return a *reference*, otherwise chaining the operator like a = b = c won't work. A typical operator = overload will look like this
M & operator = (const M& val)
{
// do the job
return *this;
}
Regards
Senthil
My Blog
|
|
|
|
|
Hi,
yes you are right about the implementation.
But you can write a program and a class, with Copy contructor and operator= implemented , and write cout statements to trace program flow.
Its really a tricky behaviour,
Regards,
Mohammad
|
|
|
|
|
Well, you're right. And so is the book's author, if SomeFunction returns a value and not a reference.. Both the copy constructor and operator = will get called. How? SomeFunction returns a value and the compiler invokes the copy constructor to create a temporary object. It then calls operator = on a, passing the temporary object.
And yeah, you are right, inside the overloaded assignment operator, you need to check if you have a valid pointer and if you do, delete it before copying the contents. This is not needed in a copy constructor because it can be invoked only once, when the object is created.
You need to watch out for something called return value optimization though. If you write code like this,
<br />
Class a = SomeFunction();<br />
then the compiler is free to optimize away the call to the copy constructor and instead construct a directly in place. So the above code will result in only copy constructor call, instead of the two you expect (one for the returned temporary object, one for a).
Regards
Senthil
My Blog
|
|
|
|
|
If 'a' already exists and you wish to replace it with data from anouther object then you must free any memory that your object allocated before copying the data. But to be safe, you must first determine it you can make a copy of the data. Which means if an allocation is needed, then allocate the required memory. If the allocation fails then throw an exception (or return an error condition). If the allocation is successfull, then free the previous memory pointers and set them equal to the newly allocated memory pointers. The idea here is to leave the object ('a') in the same state that it was in before the copy was attempted.
There is a differnce between the following:
MyClass a = b; // 1st - object being initialised
a = c; // 2nd object data being replaced
In the 1st case the code calls the copy constructor MyClass::MyClass(const MyClass& argumentMyClass).
In the 2nd case it calls the operater MyClass::operater=(const MyClass argumentMyClass).
The 1st case is easy, but it must(/should) throw an exception if a memory allocation fails (because constuctors do not return a failed/success value).
The 2nd case is a little different, because 'a' alrady exist. We have to free any memory associated with it, before reassigning the data pointers.
Now here is the flaw in the sytstem, if you don't delete your current objects data pointers before allocating space for the new data then there may not be enough memory to make a copy (highly unlikely - but possible). If that is the case then you are running so low on memory that it does not matter (just throw an exception or return a major error value).
General Rule: Any time a function/routine fails, the state of the object/data should remain in the state that is was in before the failure.
Sorry, I tend to get a little carried away. This is a fraction of what you may have to deal with, when it comes to copy constructors.
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
That clears it up for me.
|
|
|
|
|
Hi there
I´m working in a project that mixes managed and unmanaged code. While debuggin my unmanaged code that makes a call to a class that uses managed code I get a dialog box with this message: "There is no source code for the current location".
All the projects contained in the solution are seted to use managed extensions and the debug mode is seted to "mixed".
Any hint ou there to solve this problem?
Thanks in advance.
|
|
|
|
|
|
Thanks for the tip, but reading the msdn article
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtskLaunchingDebuggerAutomatically.asp[^] pointed in the greggm's blog, it makes reference to "desenv.exe" and I could not find desenv.exe in my system. I already installed "Debugging Tools for Windows" and still missing this file.
Like I told before, the project I'm working on is a C++ (native code) that call a dll that uses managed code and when I try to step into a function in this dll, the debugger stops and show me a message "There is no source code for the current location" along with a checkbox "Show disassembly automatically" and three buttons, OK, SHow Disassembly and help.
There is another utility that I coukd use to debug the managed code in the dll?
Thanks in advance
|
|
|
|
|
We have a CFormView based application. Within this application, some have created CDialog classes and so we have a mixture of window types. Some of our modal windows are CFormView based and some are CDialog based. The CDialog windows always have priority over the CFormView based windows. Even when I click on a window that is a CFormView, the title bar activates and the window is selected, but it cannot be brought to the front to display over the CDialog windows. Does anyone know what properties I have to enable or disable to change this behavior?
I need CFormView windows to display overtop of the other independent CDialog windows.
Best Regards,
Shawn D. Fox
|
|
|
|
|
I have a named pipe server, created using CreateNamedPipe(). Has anyone any idea how can I make it disallow remote clients (so only pipe clients on the same system as the server are allowed to connect to it) ?
Many thanks for any help.
Thanks,
Neil Humphreys.
|
|
|
|
|
I have an MFC application in which I need to perform a join operation of two tables Emp and Assets, with the EmpID field being the primary key. I did not use any AppWizard options to implement database connectivity functionality. Instead, I added two classes derived from CRecordset and two forms derived from CRecordview class to implement DBMS. I need to select all asets for a given EmpID in the Emp table and show the on a form. Is there a way to do this without using the m_strFilter variable/parameter stuff?
log live the dEvIL
|
|
|
|
|
I think you need to derive a class from CRecordset that has as its member variables all columns returned from the query. For example. given the following two tables:
Table1
=======
CustID
Name
Address
Phone
Table2
=======
OrderID
CustID
Total
the CRecordset -derived class would have a query that looked like:
SELECT Table1.Name, Table1.Address, Table1.Phone, Table2.Total
FROM Table1 INNER JOIN Table2 ON Table1.CustID = Table2.CustID
The class would need four member variables. Does this get you close?
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
Na, I am way too far. I did derive a class from CREcordset and linked it up to a table, I just need to set the filter. How do I do that?
long live the dEvIL
|
|
|
|
|
If you already have a CRecordset -derived class, and the subject of this thread indicates you want to implement a join, why not just change the value returned from the GetDefaultSQL() method? Using the m_strFilter member variable does not do the same thing as a join operation.
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow
|
|
|
|
|
Hello
Can anybody explain to me why the following four bold lines of code yield different results to their counterparts on the line below? By my reckoning the results should be the same with the only difference being one set are printed to the console window and the other to a text file. The purple lines are definitely creating correct results because they are a product of help code for Microsoft Visual Studio .NET and the results look good. The red lines of code (my code) are definitely producing incorrect results and all four of the outputs are often identical. Am I doing some memory management incorrectly???
#include "stdafx.h"
#using
#include
#include
#include
using namespace System;
// This is the entry point for this application
int _tmain(void)
{
_int64 ctr1 = 0, ctr2 = 0, freq = 0;
int acc = 0, i = 0;
FILE *storage;
//Start timing the code
if(QueryPerformanceCounter((LARGE_INTEGER *)&ctr1) != 0)
{
storage = fopen("C:\\TestTimer.txt", "a"); //Open a file for data output
//Code segment is being timed
for(i=0; i<100; i++) acc++;
//Finish timing the code
QueryPerformanceCounter((LARGE_INTEGER *)&ctr2);
fprintf(storage, "Start Value %s\n", ctr1.ToString());Console::WriteLine("Start Value: {0}",ctr1.ToString());
fprintf(storage, "End Value %s\n", ctr2.ToString());
Console::WriteLine("End Value: {0}",ctr2.ToString());
QueryPerformanceFrequency((LARGE_INTEGER *)&freq);
fprintf(storage, "Frequency %s\n", freq.ToString());Console::WriteLine(S"QueryPerformanceCounter minimum resolution: 1/{0} seconds.",freq.ToString());
fprintf(storage, "Time %s\n", ((ctr2-ctr1) * 1.0 / freq).ToString()); Console::WriteLine("100 Increment time: {0} seconds.",((ctr2-ctr1) * 1.0 / freq).ToString());
fclose(storage);
}
return 0;
}
|
|
|
|
|
You're mixing CLR strings with C-style strings. fprintf() expects a const char* on the stack, to be inserted where the %s is, however what you're putting on the stack is a whole System::String object, which is totally not the same thing. You need to convert that object to a C-style string (with PtrToStringChars , for example).
--Mike--
LINKS~! Ericahist updated! | 1ClickPicGrabber | CP SearchBar v2.0.2 | C++ Forum FAQ
Strange things are afoot at the U+004B U+20DD
|
|
|
|
|
hello,
i'd like to have a progress control in each MDI document's frame, which holds a CScrollView. in particular, i'm interested in shortening the horizontal scrollbar in a CScrollView, and placing controls to the left of the scrollbar, something like the output view in MSVC 6, or like excel. i searched the articles for something like this, but couldn't find anything. does anyone have any suggestions regarding how to do this?
a simple (but, in my opinion, ugly) solution is to leave CScrollView alone, add a status bar to my CMDIChildWnd-derived frame class, and place the progress control in the status bar.
thanks,
ed
Edward H Herskovits
Noetic Systems Incorporated
www.noeticsystems.com
"When certainty is not enough."
|
|
|
|
|
You'll need to stop using the scrollbar that is part of the MDI Child window and use scrollbar controls instead. If you use MFC splitters in your MDI app then it will use scrollbar controls. You might want to have a look at that.
That said it seems strange to me to have porgress controls on the MDI windows. What is taking so long that you need a scroll bar at all, I have to wonder.
Neville Franks, Author of ED for Windows www.getsoft.com and Surfulater www.surfulater.com "Save what you Surf"
|
|
|
|
|
i've developed a user interface to some number-crunching code; the user may want to analyze several documents at once without the GUI freezing, so i converted the analysis code to run in separate worker threads. i wanted to indicate progress for each document separately, rather than in the main frame's status bar, so i thought about having a progress control associated with each document/MDIChildWnd.
thanks for the advice.
ed
Edward H Herskovits
Noetic Systems Incorporated
www.noeticsystems.com
"When certainty is not enough."
|
|
|
|
|
ehh wrote:
i've developed a user interface to some number-crunching code; the user may want to analyze several documents at once without the GUI freezing, so i converted the analysis code to run in separate worker threads. i wanted to indicate progress for each document separately, rather than in the main frame's status bar, so i thought about having a progress control associated with each document/MDIChildWnd.
Ok that makes sense now. Look at the MFC CSplitterWnd code and how it uses CScrollBar. It might be easier to switch to using CSplitterWnd the you'll get the scrollbar's you need. I don't know what would be involved in reducing there size though.
Neville Franks, Author of ED for Windows www.getsoft.com and Surfulater www.surfulater.com "Save what you Surf"
|
|
|
|
|
what about adding a progress control below the view in the MDIChildWnd frame? has that been done?
thanks for your advice; i'll check out CSplitterWnd....
ed
Edward H Herskovits
Noetic Systems Incorporated
www.noeticsystems.com
"When certainty is not enough."
|
|
|
|
|
ehh wrote:
what about adding a progress control below the view in the MDIChildWnd frame? has that been done?
thanks for your advice; i'll check out CSplitterWnd....
I think it would be quite difficult to do as the View window is closely bound to the MDI window. But with enough time anything is possible.
Just did a quick Google search for "CScrollbar MDI" and found:
http://www.codeproject.com/splitter/ruler.asp[^] which may be of interest.
Neville Franks, Author of ED for Windows www.getsoft.com and Surfulater www.surfulater.com "Save what you Surf"
|
|
|
|
|