|
I forgot STL meant standard template library.
I had a look at some implementations of smart pointers and found some of the techniques interesting but tending on ugly then I thought of a pretty ideal simple solution to the problem. This class will work to allow elements in a dynamic array to be modified while preventing the user from allocating / deallocating memory for the array itself :
template<class TKey, class TValue>
class SpecialMap
{
public:
template<class TKey, class TValue>
class InternalArray
{
protected:
friend SpecialMap<TKey, TValue>;
TValue* pElements;
public:
TValue & operator[](UINT nIndex)const {return pElements[nIndex];}
};
So a user knows they shouldn't manage the memory for the array.
And it's still possible to use the array in functions requiring a void* as I mentioned for example by using &internalArray[0].
For what my program's supposed to do I think it would be a great deal more convenient using my custom container than standard ones but I will try to stick to the standards when possible.
|
|
|
|
|
What you say about smart pointers looking ugly. Absolutely true, template code is not easy to read and looks complicated at first because it is more abstract, on the other side using it is very very easy. Once you get used to the (object oriented) idea of memory being handled by smart containers/pointers, you don't miss old-school manual memory allocation. After all it is 2010 now!
From looking at your code... why don't you use a class inherited from std::vector<TValue> and make some methods you don't want to expose (e.g. resize and clear) protected?
/M
|
|
|
|
|
I was going to have a look at the boost shared / smart pointers that have definately been well implememented but I downloaded boost and my computer started playing up, well the file menu in the boost zip folder stopped working, and it was fine in other zip folders. No virus's detected. So I'll stay away from smart pointers at the moment cause I don't need them (although technically maybe the InternalArray class is a kind of smart pointer cause it is used like a pointer and means delete can't be called on it).
I don't want to use a vector because with full optimizations vector lookups are about 8200 times slower than dynamic arrays meaning you could do 8200 * 1000000 accesses to elements using a dynamic array in the time it takes to do 1000000 using a vector, which should make a fair difference in the program i'm writing and it's not only the resize and clear functions that call element destructors, even inserting an element will call destructors for all the other elements in the vector, or at least the ones that change position in the internal array. I don't see why a standard container would be implemented so destructors of elements are called when the array is resized, but of course I know why it works like that just not why someone decided to implement a vector / map etc. like that.
well, I'm happy with the code I've written
thanks for the advice / suggestions
|
|
|
|
|
Actually, I was wrong about optimisation being a problem, the vector's only slower when using the overloaded subscript operator to access elements but it's possible to make a pointer to the vector's internal array by getting the address of the first element so elements can be accessed using the pointer when faster accesses are needed. But this would mean a pointer would have to be made that holds the address which could be a bit crude to program.
|
|
|
|
|
doug25 wrote: I don't want to use a vector because with full optimizations vector lookups are about 8200 times slower than dynamic arrays
Strange, I can not confirm this behaviour in my software. I don't know what you mean by "lookups", but basic read/write access with vectors should be really fast. Here is a pseudo code to read a file into memory:
CFileStream file;
if(file.Open(sFileName, CFileStream::STREAM_READ))
{
std::vector<unsigned char> buffer;
buffer.reserve(file.GetSize());
file.Read(&buffer[0], file.GetSize());
}
doug25 wrote: even inserting an element will call destructors for all the other elements in the vector
This is by design. Vectors use a single continuous block of memory, so when you insert one element a couple of elements need to be relocated to make space in the middle. If you take for example a vector<unsigned char> this gives you pretty much the same memory access as using a block of dynamically allocated bytes. There are other STL containers with different memory layouts and runtime behaviours (lists, maps, etc).
So long,
M
|
|
|
|
|
By "lookups" I just meant accessing an element by using the subscript operator e.g. vec[nIndex].
I took a more accurate reading. For accessing a million elements, using a dynamic array e.g. value = pArray[i] is 8455 times faster (on my pc) than using the overloaded subscript operator on a vector e.g. value = vec[i] where ints are used as elements.
I'm sorted though cause I've made my own array handling functions, so I can safely use arrays. The functions make use of operator new, operator delete and placement new when required and this means I have control over how constructors / destructors are called when I need to resize array's etc.
|
|
|
|
|
doug25 wrote: 8455 times faster (on my pc)
STL is a heavily optimized library. If you have found such a difference, your benchmark is most likely doing something wrong. Make sure to compile in release mode, not debug. The performance for accessing elements is the same, whether you use std::vector or not.
Cheers
/M
|
|
|
|
|
There's virtually no performance difference between a vector and dynamic array most of the time, I agree.
I'm certain my measurements are correct but I decided to take a few more to get a better idea of the exact difference.
The test program was compiled in release mode with full optimizations, Maximize Speed, Favor fast code, no debug info...
The results show that reading values stored in a dynamic array can be anywhere from 1 times faster and above compared to reading values from a vector in the normal way i.e. using the overloaded subscript operator.
When fewer accesses are made, there will be virtually no difference in the time taken by a vector and dynamic array i.e. dynamic array is 1... times faster than vector, but if a million accesses are done at once, array is about 8000 times faster. Not quite sure why, but that's how it works.
Certain 3d computations for example might benefit from the extra performance that using dynamic arrays directly can provide. When I started using C++, I came accross a program that could help manipulate pixels on the screen faster than using e.g. windows GDI, I converted the vectors used to dynamic arrays and got a massive difference in performance on a fast computer (that was two years ago, so it's still a "fast computer"). But that was unusual, so probably vectors are almost always the best way to go.
modified on Wednesday, January 6, 2010 11:48 PM
|
|
|
|
|
doug25 wrote: When fewer accesses are made, there will be virtually no difference in the time taken by a vector and dynamic array i.e. dynamic array is 1... times faster than vector, but if a million accesses are done at once, array is about 8000 times faster. Not quite sure why, but that's how it works.
I just want to add, that STL performance was heavily studied over the past years and I have not come across anyone with your benchmark results. Happy testing!
|
|
|
|
|
thanks
|
|
|
|
|
Hi everyone! Hope you all had a great New Years Eve!!
In my adio mixer GUI, I have a group of GUI objects each containing a level slider. They are instances of the class "ChannelStrip". Each channel strip also contains "group buttons" that are supposed to link channels together so that a change of the slider position on one channel will also apply to all the other in the same group.
In order to accomplish this I tried to create a class "ChannelGroup" which the ChannelStrip class inherited from. The idea was to put a function "sliderGroupEdit" and pointers to all the ChannelStrips in the ChannelGroup class and call sliderGroupEdit from callbacks for the sliders.
I never got it to work. It seems as if the problem has something to do with the base class using its child class. Both need the other to be defined to be defined!
My questions are:
1) Is this a good way to plan the program or am I making things unnecessarily complicated?
2) Is it even possible for a parent class to have its children as member variables?
3) Is it a good idea to put everything in .h-files like I do?
4) Is there a standard solution to the problem of making objects of the same class communicate?
As you probably guessed I am a beginner and I would be very thankful for any help! Maybe I should also add that I am using the Juce class library.
Have a great day!
ChannelGroup.h :
class ChannelGroup : public Component
{
private:
int nrOfChannels;
ChannelStrip * pChStripArray;
...
public:
...
ChannelGroup(int nrOfChs)
{
nrOfChannels = nrOfChs;
pChStripArray = new ChannelStrip[nrOfChannels];
...
}
void sliderGroupEdit(int groupNr, double dBLevel )
{
for (int k=0; k<nrOfChannels; k++)
{
pChStripArray[k].levelSlider->setValue(dBLevel);
}
}
}
ChannelStrip.h :
...
class ChannelStrip : public ChannelGroup
{
...
void sliderValueChanged(Slider *slider)
{
...
ChannelGroup::sliderGroupEdit( groupNr, dBLevel );
}
};
|
|
|
|
|
Looking to your problem briefly I would try a Channelgroup-class that holds several Channelstrips, by a method AddChannelstrip(). The Channelstrip-class will have a property Owner that is a reference to the Channelgroup. In this way both classes have acces to eachother...
Rozis
|
|
|
|
|
Rozis,
Thanks for answering my distress call. I will try what you suggested!
|
|
|
|
|
Hi,
I am using VS2008 SP1 On Widows 7 X64, once I have decided to use the XmlLite parser in my program I faced the following problem
Error 1 error LNK2019: unresolved external symbol _CreateXmlReader@12 referenced in function
"public: void __thiscall CXmlLiteSampleAppDlg::OnBnClickedButtonOpenXmlFile(void)"
(?OnBnClickedButtonOpenXmlFile@CXmlLiteSampleAppDlg@@QAEXXZ) XmlLiteSampleAppDlg.obj
and here is my code:
void CXmlLiteSampleAppDlg::OnBnClickedButtonOpenXmlFile()
{
CFileDialog fDlg(true,L"xml",NULL,
OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_EXPLORER,
L"XML Files (*.xml)|*.xml||",
this,NULL,true);
if(fDlg.DoModal()==IDOK){
CString fileName(fDlg.GetPathName());
::SHCreateStreamOnFileW(fileName,
STGM_READWRITE | STGM_SHARE_DENY_WRITE,&m_pFileStream);
HRESULT hr = ::CreateXmlReader(
__uuidof(IXmlReader),reinterpret_cast<void**>(&m_pXMLReader),NULL);
if(FAILED(hr)){
_com_error err(hr);
::AfxMessageBox(err.ErrorMessage());
return;
}
}
}
and my definitions of IStream and IXmlReader is like below:
CComPtr <IStream> m_pFileStream;
CComPt <IXmlReader> m_pXMLReader;
Of course while surfing the net I find similar problem in this thread:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/fad815c9-0de3-4c97-a6a6-12d04a958013
and I have done all solution discussed there but non of them solve my problem.
Also I have added
$(WindowsSdkDir)\lib to the C++ Directories but this effort were in vain too.
|
|
|
|
|
|
The missing symbol the compiler was looking for was CreateXmlReader, I know the compiler indicated that the problem was in your dialog class, it's a common red herring, but once you know how to read these linker error messages, it gets easier
If adding a library path instead (if all you have is the .lib file), you will want to check that the library is added for debug and release builds. Configuring a project dependency as in the previous solution is thus best.
Conrad -
The world waits for you to stick your neck out, it's not easy. But once you actually stand up, you do get noticed.
http://www.plcsimulator.org/
|
|
|
|
|
I am trying to install a "WebDisk" from my website host and I get the following error message from Internet Explorer "The web folder is not available. Please insure that the port is not firewalled." The port IS NOT firewalled yet I continue to get this error message. I tried to manually create the web disk folder and I get the same thing. Without the web disk folder I cannot upload files for my website. Any suggestions?
A C++ programming language novice, but striving to learn
|
|
|
|
|
I define a class like this :
<br />
class Test<br />
{<br />
private:<br />
static Test* instance;<br />
<br />
private:<br />
typedef void (Test::*SayHello)(char*);<br />
<br />
SayHello sayHello;<br />
<br />
void Say(char* name)<br />
{<br />
cout<< "Hello " <<name;<br />
}<br />
<br />
static void test()<br />
{<br />
instance->*sayHello("hello");
}<br />
<br />
public:<br />
Test()<br />
{<br />
sayHello = &Test::Say;<br />
}<br />
~Test()<br />
{<br />
<br />
}<br />
<br />
static Test* getInstance()<br />
{<br />
if(instance == NULL)<br />
instance = new Test();<br />
return instance;<br />
} <br />
};<br />
When compiling i receive some error messages :
<br />
error C2597: illegal reference to non-static member 'Test::sayHello'<br />
<br />
error C3867: 'Test::sayHello': function call missing argument list; use '&Test::sayHello' to create a pointer to member<br />
<br />
error C2568: '->*' : unable to resolve function overload<br />
If you have any ideas plz tell me
Thanks in advance
|
|
|
|
|
A static function can be called without creating an instance of the class. But the member function pointer needs the class instance to call the function. So, the compiler doesn't allow calling a non-static member function from a static function.
|
|
|
|
|
But i did have a private static instance of Test class , and i use that to call the function pointer
|
|
|
|
|
You can't access instance members from a static method. Also the singleton implementation is wrong and your example doesn't make sense at all. Here is a modified version of your code which compiles fine.
class Test
{
private:
typedef void (Test::*SayHello)(char*);
SayHello sayHello;
Test()
{
sayHello = &Test::Say;
}
Test(const Test&);
Test& operator=(const Test&);
void Say(char* name)
{
cout<< "Hello " << name;
}
static void test()
{
Test* instance = Test::getInstance();
instance->FireSayHello("hello");
}
public:
void FireSayHello(char* message)
{
(*this.*sayHello)(message);
}
static Test* getInstance()
{
static Test instance;
return &instance;
}
};
Best wishes,
Navaneeth
|
|
|
|
|
Hello Everybody,
I am new to the windows 32 api and i am trying to use the win 3 api function CreateProcess.
I am simply trying to use this function to open the msn messanger process on my windows 7 pc, but i keep on getting a 0 exit code(failure). this is my code:
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
void _tmain( )
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory( &si, sizeof(si) );
si.cb = sizeof(si);
ZeroMemory( &pi, sizeof(pi) );
// Start the child process.
if( !CreateProcess( "c:\Program Files\Windows Live\Messenger\msnmsgr.exe", // module name (use command line)
NULL, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi ) // Pointer to PROCESS_INFORMATION structure
)
{
printf( "CreateProcess failed (%d).\n", GetLastError() );
return;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
}
the path c:\Program Files\Windows Live\Messenger\msnmsgr.exe is my msn messanger directory, but somehow i can get it to work.
Can someone please help me?
Thanks,
Nir Winter
|
|
|
|
|
only two things I can think of
1) try running [c:\Program Files\Windows Live\Messenger\msnmsgr.exe] from the command line from a dos/cmd prompt, see if that starts on its own, and/or double click it in explorer - hopefully this step will prove that its the right exe and doesnt need any parameters
2) I think the use of your module and command line args are slightly incorrect - I would repeat the [c:\Program Files\Windows Live\Messenger\msnmsgr.exe] in the commandline parameter of the createprocess api, so in effect the module name == the command line IN THIS CASE instead of the NULL you specified - if there were startup options [for example /s para-whatever] you would then end up with
if( !CreateProcess("c:\Program Files\Windows Live\Messenger\msnmsgr.exe", // module
"c:\Program Files\Windows Live\Messenger\msnmsgr.exe /s para-whatever", // commandline
NULL, //process handler
...
|
|
|
|
|
Don't you need two \ characters for literal character strings?
"c:\\Program Files\\Windows Live\\Messenger\\msnmsgr.exe",
|
|
|
|
|
I checked your code against mine and see the following differences:
- Creation flags. I use: normal_priority_class+CREATE_NEW_PROCESS_GROUP
- I use CreateProcess(NULL,"C:\Program files....". Thus turn the first 2 arguments.
- Try parent starting directory "c:\Program Files\Windows Live\Messenger". Or try to run something in the windows folder. Guess that the folder is not accessable. As mentioned try to run
it manually from the commandline.
- Set si.wShowWindow to SW_SHOWNORMAL
Does this help?
Rozis
|
|
|
|
|