Constructing a child object from parent object in C++ - rvalue-reference

I am trying to construct a child class object from a base class object. I have tried the below code.
class A
{
public:
A();
A(A&& objectName) = default;
virtual void setint(int i);
virtual void getint();
int var;
};
class B: public A
{
public:
virtual void getint();
B(A&& objectName);
int j= 20;
};
A::A()
{
}
void A::setint(int i)
{
var = i;
}
void A::getint()
{
qDebug()<<"From A Var"<<var;
}
void B::getint()
{
qDebug()<<"From B j"<<j;
qDebug()<<"From B Var"<<var;
}
B::B(A&& objectName): A(std::move(objectName))
{
}
And in my Main.cpp I am doing this
#include <memory>
int main(int argc, char *argv[])
{
A *obj = new A();
obj->setint(10);
obj->getint();
A *obj1 = new B(std::move(*obj));
obj->getint();
obj1->getint();
return 0;
}
The result I get is
From A Var 10
From A Var 10
From B j 20
From B Var 10
My question is why am I getting the value of Var after A *obj1 = new B(std::move(*obj)); this line. I thought the object pointed by obj must have been destructed.

Let me copy paste from this answer: https://stackoverflow.com/a/15663912/512225
std::move doesn't move from the object. It just returns an rvalue reference whose referand is the object, making it possible to move from the object.
Anyway your code is terrible. I hope you know. If you don't, ask for a review.

Related

How to get extra data from MFC Tab Control (TabCtrl)?

I have created an MFC dialog based application to study tab control. In a tab control it is possible to set application specific data to each tab.
I am trying to understand how to set/retrieve the data for individual tabs of the tab control.
Here is a sample application I am creating. Each tab of the control is supposed to store some GPU info.
As I understand, there are 3 steps to add application specific data.
Create a user defined structure, whose 1st member should be of type TCITEMHEADER.
struct GPU {
std::wstring name;
int busid;
};
struct tabData {
TCITEMHEADER tabItemHeader;
GPU gpu;
};
Tell the tab control about the extra bytes, the user defined structure is going to take. This I am doing in DoDataExchange().
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
Set user defined data while adding tabs.
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
Now to get the data, we simply have to call TabCtrl_GetItem().
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2);
But as we can see in the following image. I do get the tab text (pszText member - data Item 1 in image), but not the extra data that I had associated with it previously (Data Items 2 and 3 in image).
Which step am I missing?
Why is the structure associated with application defined data not getting populated?
Additional Info
Here is the complete code for the application.
CPP File:
// tabCtrlStackOverflowDlg.cpp : implementation file
//
#include "stdafx.h"
#include "tabCtrlStackOverflow.h"
#include "tabCtrlStackOverflowDlg.h"
#include "afxdialogex.h"
#include <string>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct GPU {
std::wstring name;
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
CtabCtrlStackOverflowDlg::CtabCtrlStackOverflowDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_TABCTRLSTACKOVERFLOW_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CtabCtrlStackOverflowDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TAB1, tabCtrl1);
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
wchar_t *t = status ? L"SetItemExtra() success" : L"SetItemExtra() fail";
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
}
BEGIN_MESSAGE_MAP(CtabCtrlStackOverflowDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDADDTAB, &CtabCtrlStackOverflowDlg::OnBnClickedAddtab)
ON_BN_CLICKED(IDC_GETITEM0, &CtabCtrlStackOverflowDlg::OnBnClickedGetitem0)
ON_BN_CLICKED(IDCLOSE, &CtabCtrlStackOverflowDlg::OnBnClickedClose)
END_MESSAGE_MAP()
// CtabCtrlStackOverflowDlg message handlers
BOOL CtabCtrlStackOverflowDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CtabCtrlStackOverflowDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CtabCtrlStackOverflowDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CtabCtrlStackOverflowDlg::OnBnClickedAddtab()
{
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
int status = TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
wchar_t *t = L"";
if (status == -1)
{
t = L"TabCtrl_InsertItem() Fail";
}
else
{
t = L"TabCtrl_InsertItem() success";
}
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
tabCtr++;
}
void CtabCtrlStackOverflowDlg::OnBnClickedGetitem0()
{
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
if (TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2) == TRUE)
{
std::wstring text = td2.tabItemHeader.pszText;
text += std::wstring(L" ") + td2.gpu.name;
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(text.c_str());
}
else
{
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(_T("TabCtrl_GetItem()
error"));
}
}
void CtabCtrlStackOverflowDlg::OnBnClickedClose()
{
CDialog::OnCancel();
}
Header File:
// tabCtrlStackOverflowDlg.h : header file
//
#pragma once
#include "afxcmn.h"
// CtabCtrlStackOverflowDlg dialog
class CtabCtrlStackOverflowDlg : public CDialogEx
{
// Construction
public:
CtabCtrlStackOverflowDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TABCTRLSTACKOVERFLOW_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CTabCtrl tabCtrl1;
afx_msg void OnBnClickedAddtab();
afx_msg void OnBnClickedGetitem0();
afx_msg void OnBnClickedClose();
};
Solution Summary
From Barmak Shemirani's answer here are the 3 reasons my code wasn't working. Must read his answer for better understanding.
TCIF_PARAM must be set in mask, while doing TCM_INSERTITEM, and TCM_GETITEM.
I was using local variables created on stack (tabData td2; object). The reference to this variable was becoming invalid as soon as it was going out of scope.
Using std::wstring in the structure being used for TCM_INSERTITEM. It is better to use data types whose size can be accurately be determined (like plain old data types.).
As Barmak Shemirani points out in comments, the documentation for TCITEMHEADER is scarce. His answer provides a thorough explanation.
Conflict with documentation
Documentation for TCITEMHEADER does not mention using TCIF_PARAM flag. Maybe that's a mistake in documention!
It's better if SetItemExtra is moved to OnInitDialog after default procedure is called. This ensures SetItemExtra is called only once when control is empty.
The structure GPU has a std::wstring member whose data size is unknown at the start. TCM_INSERTITEM cannot make a copy of this data unless you have a simple POD structure.
To store the data in the tab, replace std::wstring with wchar_t name[100] so that data is a simple POD structure with fixed size.
struct GPU
{
//std::wstring name;
wchar_t name[100];
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
void CMyDialog::OnBnClickedAddtab()
{
int index = tab.GetItemCount();
wchar_t tabname[50];
wsprintf(tabname, L"Tab %d", index);
tabData sdata = { 0 };
sdata.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
sdata.tabItemHeader.pszText = tabname;
wsprintf(sdata.gpu.name, L"AMD NVIDIA %d", index);
sdata.gpu.busid = 101;
tab.SendMessage(TCM_INSERTITEM, index, (LPARAM)(TCITEMHEADER*)(&sdata));
}
void CMyDialog::OnBnClickedGetitem0()
{
int index = tab.GetCurSel();
tabData data = { 0 };
wchar_t buf[20] = { 0 };
data.tabItemHeader.pszText = buf;
data.tabItemHeader.cchTextMax = sizeof(buf)/sizeof(wchar_t);
data.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.SendMessage(TCM_GETITEM, index, (LPARAM)(TCITEMHEADER*)(&data)))
{
CString str;
str.Format(L"%d %s", data.gpu.busid, data.gpu.name);
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}
Alternative method:
If std::wstring name; cannot be replaced with wchar_t buffer, we have to define a separate permanent data, for example using std::vector. Then we use the lParam value in TCITEM to point to the vector.
This method only needs the standard 4 bytes of lParam, it doesn't require TCITEMHEADER and SetItemExtra. You can even define std::vector<GPU>. Example:
std::vector<tabData> m_data;
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
tabData data;
data.gpu.name = L"AMD NVIDIA1";
data.gpu.busid = 101;
m_data.push_back(data);
data.gpu.name = L"AMD NVIDIA2";
data.gpu.busid = 102;
m_data.push_back(data);
return TRUE;
}
void CMyDialog::OnBnClickedAddtab()
{
static int tabCtr = 0;
if(tabCtr >= (int)m_data.size())
return;
TCITEM item = { 0 };
item.pszText = _T("TabX");
item.mask = TCIF_TEXT | TCIF_PARAM;
item.lParam = (LPARAM)&m_data[tabCtr];
tab.InsertItem(tabCtr, &item);
tabCtr++;
}
void CMyDialog::OnBnClickedGetitem0()
{
TCITEM item = { 0 };
item.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.GetItem(tab.GetCurSel(), &item) == TRUE)
{
tabData* ptr = (tabData*)item.lParam;
CString str;
str.Format(L"%d %s", ptr->gpu.busid, ptr->gpu.name.c_str());
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}

error C2079: 'room::goldC' uses undefined class 'goldContainer'

i'm trying to create a room which has a goldContainer
The goldContainer is defined in a separate .h file.
When i'm trying to compile it says
error C2079: 'room::goldC' uses undefined class 'goldContainer'
The class voor room:
#pragma once
#include <SFML\Graphics.hpp>
#include "screenSettings.h"
#include "floorplanPatch.h"
#include "floorplanPatchContainer.h"
#include "enemyContainer.h"
#include "goldContainer.h"
class goldContainer;
class room{
public:
room(int themenr, floorplanPatchContainer &f);
void draw(sf::RenderWindow &window);
int getStartPoint();
int getEndPoint();
void addFloorplanPatch(int x, int y, int type, floorplanPatch *patch);
bool isSolid(sf::Vector2f position);
void addEnemy();
static const int FLOOR_TEXTURE1 = 0;
static const int FLOOR_TEXTURE2 = 1;
static const int FLOOR_TEXTURE3 = 2;
static const int FLOOR_TEXTURE4 = 3;
static const int WALL = 4;
static const int OBSTACLE = 5;
static const int COSMETIC = 6;
int floorplan[xAs][yAs];
enemyContainer* getEnemyContainer();
void room::addEnemy(int health);
private:
enemyContainer ec;
int startPoint = 1 + rand() % (yAs - 2);
int endPoint = 1 + rand() % (yAs - 2);
sf::RectangleShape rectangle{ sf::Vector2f{ tileSizeX, tileSizeY } };
sf::Texture wall;
sf::Texture obstacle;
sf::Texture floor1;
sf::Texture floor2;
sf::Texture floor3;
sf::Texture floor4;
sf::Texture cosmetic;
void drawBackgroundTile(sf::RenderWindow &window, int i, int x, int y);
goldContainer goldC;
};
it has class goldContainer; on line 8 otherwise it generates error code 2146.
Could someone maybe explain how to solve this error and/or why this occurs.
#pragma once
#include "gold.h"
#include "sound.h"
#include "player.h"
class player;
class room;
class goldContainer{
public:
goldContainer();
~goldContainer();
void checkPickedUp(player &player);
void draw(sf::RenderWindow &window);
void addGold(int amount, sf::Vector2f position, sf::Vector2f size);
void clearAllGold();
private:
std::vector<gold* > goldDrops;
sound goldPickup{ "sounds\\goldPickup.wav" };
};
I think it might be a circular depedency trough:
^->goldContainer->player->roomContainer->room->|
|<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-<-< v
Let me show you the problem domain:
class Moon;
class Sun
{
void Rotate(Moon);
};
Now, you implement Sun::Rotate, without giving any class declaration (not forward declaration):
void Sun::Rotate(Moon m) // Error C2027
{
}
What you can do:
Ensure that before Sun::Rotate gets into compilation phase, Moon is declared (i.e. known to compiler by now). You need not to implement any method of Moon, just declare.
Example:
class Moon;
class Sun
{
void Rotate(Moon);
};
// Let it come by now
class Moon
{
public:
void PleaseRotate();
};
// Moon is known
void Sun::Rotate(Moon m)
{
m.PleaseRotate(); // It need not to be implemented by now.
}
Note that Moon::PleaseRotate definition would be resolved by linker, and hence its implementation is not needed before Sun::Rotate.

Copying objects in C++/CLI and message passing in multithreading

I'm trying to transfer a command line code that I have to a more visual program with a
GUI to enable easier use. The original code was in C++, so I'm using Visual C++ that is
available in Visual Studio Express 2012, but I have problems understanding the "new"
managed C++/CLI way of handling objects. Being new to CLI and managed C++, I was wondering
if someone can explain what I am doing wrong, and why it doesn't work. Now here is a
description of the code and the problem.
The program is essentially an optimization program:
There are multiple boxes (modes) in a system, each mode, depending on its type has a
few numerical coefficients that control its behavior and the way it responds to outside
excitation.
The program asks the user to specify the number of boxes and the type of each box.
Then tries to find the numerical coefficients that minimize the difference between
the system response with those obtained experimentally.
So, the UI has means for user to open the experimental result files, specify the number
of modes, and specify the type of each mode. Then, the user can initiate the processing
function by clicking on a start button, that initiates a background worker.
Following the example given in MSDN, I created a class that performs the work:
ref class curveFit
{
public: ref class CurrentState{
public:
int percentage;
int iterationNo;
int stage;
bool done;
multimode systemModel;
};
public:
int modes;
int returncode;
array<double> ^expExcitations;
array<double> ^expResults;
multimode systemModel;
private:
void fcn(int, int, double*, double*, int*);
double totalError(std::vector<double> &);
public:
delegate void fcndelegate(int, int, double*, double*, int*);
public:
curveFit(void);
curveFit^ fit(System::ComponentModel::BackgroundWorker^, System::ComponentModel::DoWorkEventArgs^, Options^);
};
multimode is just a container class: a list of different boxes.
ref class multimode
{
private:
Collections::Generic::List<genericBoxModel ^>^ models;
int modes;
public:
multimode(void);
multimode(const multimode%);
int modeNo(void);
void Add(genericBoxModel^);
void Clear();
genericBoxModel^ operator[](int);
multimode% operator=(const multimode%);
double result(double);
bool isValid();
std::vector<double> MapData();
void MapData(std::vector<double> &);
};
multimode::multimode(void)
{
models = gcnew Collections::Generic::List<genericBoxModel ^>();
modes = 0;
}
multimode::multimode(const multimode% rhs)
{
models = gcnew Collections::Generic::List<genericBoxModel ^>();
for(int ind = 0; ind < rhs.modes; ind++)
models->Add(rhs.models[ind]);
modes = rhs.modes;
}
int multimode::modeNo(void)
{
return modes;
}
void multimode::Add(genericBoxModel^ model)
{
models->Add(model);
modes++;
}
void multimode::Clear()
{
models->Clear();
modes = 0;
}
genericBoxModel^ multimode::operator[](int ind)
{
return models[ind];
}
multimode% multimode::operator=(const multimode% rhs)
{
models->Clear();
for(int ind = 0; ind < rhs.modes; ind++)
models->Add(rhs.models[ind]);
modes = rhs.modes;
return *this;
}
double multimode::result(double excitation)
{
double temp = 0.0;
for(int ind = 0; ind < modes; ind++)
temp += models[ind]->result(excitation);
return temp;
}
bool multimode::isValid()
{
bool isvalid = true;
if(modes < 1)
return false;
for(int ind = 0; ind < modes; ind++)
isvalid = (isvalid && models[ind]->isValid());
return isvalid;
}
std::vector<double> multimode::fullMap()
{
//Map the model coefficients to a vector of doubles
...
}
void multimode::fullMap(std::vector<double> &data)
{
//Map a vector of doubles to the model coefficients
...
}
and genericBoxModel is an abstract class that all box models are based on.
The curvefit::fit function does the optimization based on the options passed to it:
curveFit^ curveFit::fit(System::ComponentModel::BackgroundWorker^ worker, System::ComponentModel::DoWorkEventArgs^ e, Options^ opts)
{
fcndelegate^ del = gcnew fcndelegate(this, &curveFit::fcn);
std::vector<double> data;
CurrentState^ state = gcnew CurrentState;
state->done = false;
state->stage = 0;
state->percentage = 0;
state->systemModel = systemModel;
worker->ReportProgress(state->percentage, state);
switch(opts->optimizationMethod)
{
case 0:
while(iterationNo < maxIterations)
{
data = systemModel.MapData();
OptimizationMethod0::step(some_parameters, data, (optmethods::costfunction)Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(del).ToPointer());
systemModel.MapData(data);
iterationNo++;
state->percentage = 0;
state->systemModel = systemModel;
worker->ReportProgress(state->percentage, state);
}
...
}
}
I'm passing the system model inside the state so that I can display the results of the
latest step on the screen, which doesn't work, but that is another question :-)
The start button calls the curvefit::fit function after initializing the system model:
private: System::Void btnStart_Click(System::Object^ sender, System::EventArgs^ e) {
systemModel.Clear();
for(int mode = 0; mode < modes; mode++)
{
switch(model)
{
case 0:
systemModel.Add(gcnew model0);
systemModel[mode]->coefficients[0] = 100.0 / double(mode + 1);
...
break;
...
}
}
btnStart->Enabled = false;
stStatusText->Text = "Calculating!";
Application::UseWaitCursor = true;
curveFit^ cf = gcnew curveFit;
fitCurve->RunWorkerAsync(cf);
}
private: System::Void fitCurve_DoWork(System::Object^ sender, System::ComponentModel::DoWorkEventArgs^ e) {
System::ComponentModel::BackgroundWorker^ worker;
worker = dynamic_cast<System::ComponentModel::BackgroundWorker^>(sender);
curveFit^ cf = safe_cast<curveFit^>(e->Argument);
cf->expExcitations = gcnew array<double>(expExcitations.Count);
expExcitations.CopyTo(cf->expExcitations);
cf->expResults = gcnew array<double>(expResults.Count);
expResults.CopyTo(cf->expResults);
cf->systemModel = systemModel;
cf->modes = modes;
e->Result = cf->fit(worker, e, options);
}
This works perfectly! But, in order to make the optimization process faster and more
successful, I wanted to use the results of previous optimizations as the initial guess
for the next run (if possible):
multimode oldmodel(systemModel);
systemModel.Clear();
for(int mode = 0; mode < modes; mode++)
{
switch(model)
{
case 0:
if(mode < oldmodel.modeNo() && oldmodel.isValid() && (oldmodel[mode]->model == 0))
systemModel.Add(oldmodel[mode]);
else
{
systemModel.Add(gcnew model0);
systemModel[mode]->coefficients[0] = 100.0 / double(mode + 1);
...
}
break;
...
Now, my problem is, after this change, it seems that the messages don't get passed
correctly: the first time the start button is clicked everything functions as it should,
but from then on, if the statement systemModel.Add(oldmodel[mode]); gets executed,
results remain the same as the initial guesses, and don't get updated after the fit
function is called.
So, why should these two lines(Add(oldmodel[mode]) and Add(gcnew model0)) give
such different results?

boost::shared_array assignment crashes application(VC++ 2010)

Modified the below circular queue code for my app.
This queue can hold 32 elements max and I have declared the elements as a structure array inside the class. For adding an element to the queue you have to call CreateElement() functions, which checks for a free element and returns an index. When I reuse an element after processing the following line in the CreateElement functions crashes
boost::shared_array<char> tData(new char[bufferSize]);
m_QueueStructure[queueElems].data = tData;
As per documentation, the assignment operator is supposed to destroy the earlier object and assign the new one. Why is it crashing? Can someone tell me where am I screwing?
#include "boost/thread/condition.hpp"
#include "boost/smart_ptr/shared_array.hpp"
#include <queue>
#define MAX_QUEUE_ELEMENTS 32
typedef struct queue_elem
{
bool inUse;
int index;
int packetType;
unsigned long compressedLength;
unsigned long uncompressedLength;
boost::shared_array<char> data;
}Data;
class CQueue
{
private:
int m_CurrentElementsOfQueue;
std::queue<Data> the_queue;
mutable boost::mutex the_mutex;
boost::condition_variable the_condition_variable;
Data m_QueueStructure[MAX_QUEUE_ELEMENTS];
public:
CQueue()
{
m_CurrentElementsOfQueue = 0;
for(int i = 0; i < MAX_QUEUE_ELEMENTS; i++)
{
m_QueueStructure[i].inUse = false;
m_QueueStructure[i].index = i;
}
}
~CQueue()
{
for(int i = 0; i < m_CurrentElementsOfQueue; i++)
{
int index = wait_and_pop();
Data& popped_value = m_QueueStructure[index];
popped_value.inUse = false;
}
m_CurrentElementsOfQueue = 0;
}
void push(Data const& data)
{
boost::mutex::scoped_lock lock(the_mutex);
the_queue.push(data);
lock.unlock();
the_condition_variable.notify_one();
}
bool empty() const
{
boost::mutex::scoped_lock lock(the_mutex);
return the_queue.empty();
}
bool try_pop(Data& popped_value)
{
boost::mutex::scoped_lock lock(the_mutex);
if(the_queue.empty())
{
return false;
}
popped_value=the_queue.front();
the_queue.pop();
return true;
}
int wait_and_pop()
{
boost::mutex::scoped_lock lock(the_mutex);
while(the_queue.empty())
{
the_condition_variable.wait(lock);
}
Data& popped_value=the_queue.front();
the_queue.pop();
return popped_value.index;
}
int CreateElement(int bufferSize, unsigned long _compressedLength,
unsigned long _uncompressedLength, int _packetType) /* Send data length for this function */
{
int queueElems = 0;
if(m_CurrentElementsOfQueue == 32)
{
CCommonException ex(QERROR, QUEUE_FULL, "Circular Buffer Queue is full");
throw ex;
}
for(queueElems = 0; queueElems < MAX_QUEUE_ELEMENTS; queueElems++)
{
if(m_QueueStructure[queueElems].inUse == false)
break;
}
boost::shared_array<char> tData(new char[bufferSize]);
m_QueueStructure[queueElems].data = tData;
m_QueueStructure[queueElems].inUse = true;
m_QueueStructure[queueElems].compressedLength = _compressedLength;
m_QueueStructure[queueElems].uncompressedLength = _uncompressedLength;
m_QueueStructure[queueElems].packetType = _packetType;
m_CurrentElementsOfQueue++;
return queueElems;
}
Data& GetElement(int index)
{
Data& DataElement = m_QueueStructure[index];
return DataElement;
}
void ClearElementIndex(Data& delValue)
{
m_CurrentElementsOfQueue--;
delValue.inUse = false;
}
};
for(queueElems = 0; queueElems < MAX_QUEUE_ELEMENTS; queueElems++) after looping queueElems has value 32 but in your m_QueueStructure only 32 elements so you trying to access m_QueueStructure[queueElems].data to 33rd element. That the problem.
EDIT: try use m_QueueStructure[queueElems].data.reset(new char[bufferSize]);
Solved the problem. Two changes I did. In the wait_and_pop function, I was returning an index rather than a Data&. When I returned Data&, that solved the assignment problem. Another crash was happening due to a memset of a shared_array.get(). Lesson learnt, never memset a shared_array or a shared_ptr.

Convert .Net ref (%) to native (&)

How can I convert a C++/CLI int %tmp to native C++ int &tmp?
void test(int %tmp)
{
// here I need int &tmp2 for another pure C++ function call
}
Neither of the existing answers properly handle in/out parameters, let alone any advanced use cases.
This should work for all cases where other_func does not keep the reference after it returns:
void test(int %tmp)
{
pin_ptr<int> pinned_tmp = &tmp;
other_func(*pinned_tmp);
}
Just tried this, works fine:
//in the C++ dll
void testFunc( int& n )
{
n = 5;
}
//in the CLI app
[DllImport( "my.dll", EntryPoint = "?exported_name_here",
CallingConvention = CallingConvention::StdCall )]
void TestFunc( int& );
void test( int% tmp )
{
int n;
TestFunc( n );
tmp = n;
}
void your_function(int *);
void your_function2(int &);
void test(int %tmp)
{
int tmp2;
your_function(&tmp2);
your_function2(tmp2);
tmp=tmp2;
}

Resources