传回从向量中检索的指针的问题 [英] Issue with passing back a pointer retrieved from a vector

查看:67
本文介绍了传回从向量中检索的指针的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你好!在经历了13年失去我真正的编程技巧后,我决定重新回到C ++。我写了一个小程序,从网络摄像头读取并显示输出,现在我要回去尝试从这个应用程序中创建一个框架。我有一种方法不能按我的预期工作,我相信这里的专家可以提供帮助。



这就是我所拥有的。此方法询问设备驱动程序以提取有关设备的信息,并构建存储此信息的对象,然后将该对象放在向量中。这似乎工作正常。



 HRESULT WebCamDeviceList :: RegisterDevice(UINT32索引,IMFActivate * vDevice,IMFMediaSource * vMediaSource,IMFSourceReader * vMediaReader){ 
HRESULT hr = S_OK;
LPWSTR dFriendlyName = NULL;
UINT32 dName = NULL;
// dFriendlyName返回已分配的内存,需要清理为
//点
hr = vDevice [index] .GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME,& dFriendlyName,& dName);

if(SUCCEEDED(hr)){
WebCamDevice * wDevice = new WebCamDevice();

wDevice-> SetIndex(index);
wDevice-> SetName(dName);
wDevice-> SetFriendlyName(dFriendlyName);

wDevice-> LoadConfiguration(vMediaSource,vMediaReader);

_DeviceList.push_back(wDevice);

} else {
MessageBox(NULL,TEXT(无法读取设备名称),TEXT(错误!),MB_ICONEXCLAMATION | MB_OK);
}


return hr;
}





这段代码从向量中检索该对象指针并将其传递回调用者。使用调试器检索对象指针似乎工作正常。问题是device参数被传回,没有任何值,就像它超出范围一样,如果是Java,我会认为GCer得到它。





 HRESULT WebCamDeviceList :: GetDevice(size_t index,WebCamDevice ** device){
HRESULT hr = S_OK;
WebCamDevice * cDevice = NULL;
if(index< _DeviceList.size()){
cDevice = _DeviceList [index];
}
device =& cDevice;
返回小时;
}







如果这有帮助,请拨打电话。行deviceList-> GetDevice(index,& device)传回一个空对象,即使它在退出之前就可以看到指针对调试器是有效的。



 WebCamDeviceList * deviceList = new WebCamDeviceList(); 
deviceList-> LoadDevices();
deviceList-> GetCount(& numberDevices);

size_t index = 0;

mainWindow =新的GuiMain(hWnd,hInstance);
while(index< numberDevices){
// MessageBox(NULL,TEXT(Device One),TEXT(Error!),MB_ICONEXCLAMATION | MB_OK);
WebCamDevice * device = NULL;
deviceList-> GetDevice(index,& device);
//((WebCamVideoConfig *)(device-> VideoConfig) - > WebCamVideoConfig :: SetWidth(width);
if(device-> GetFriendlyName()!= NULL){
SendMessage(mainWindow-> DeviceListBox,LB_ADDSTRING,0,(LPARAM)device-> GetFriendlyName());
}
index ++;
}





这必须是非常简单的事情我觉得傻瓜不理解发生了什么,因为我以前这样做是为了谋生但是Java已经毁了我的指针和记忆管理技巧。



提前感谢您的帮助。

Kevin

解决方案

编辑:这是没有修改的错误代码:

 HRESULT WebCamDeviceList :: GetDevice( size_t  index,WebCamDevice ** device){
HRESULT hr = S_OK;
WebCamDevice * cDevice = NULL;
if (index< _DeviceList.size()){
cDevice = _DeviceList [index];
}
device =& cDevice;
return hr;
}



C / C ++中的函数参数就像局部变量一样(java也是如此,这里没有魔法)。使用 device =& cDevice; ,您可以设置指针局部变量的值。我想你想做 * device = cDevice; device [0] = cDevice; 具有相同的效果。或者,如果我们正在谈论C ++而不是CI会写:

 HRESULT WebCamDeviceList :: GetDevice( size_t  index,WebCamDevice *& device){
device = index< _DeviceList.size()? _DeviceList [index] :( WebCamDevice *)NULL;
return S_OK;
}





deviceList-> GetDevice(index,device);

而不是

deviceList-> GetDevice(index,& device);



编辑:在C ++中,如果它不能为NULL,则使用引用而不是指针。这不仅是幻想,它可以帮助您避免这样的错误及其文档。如果有人看了你的函数/方法声明,她会立即知道引用参数不能为NULL,而双指针或指针指针总是不明确的。你使用你编码的丑陋的指针指针和指针指针指针越多。在C ++中,如果你编写好的代码,你很少需要多个指针间接。



编辑:因为你总是返回S_OK,你可以简单地将你的功能改为:

 WebCamDevice * WebCamDeviceList :: GetDevice( size_t  index){
return index< _DeviceList.size()? _DeviceList [index] :( WebCamDevice *)NULL;
}



或者这个相同,但更容易将断点放入分支:

 WebCamDevice * WebCamDeviceList :: GetDevice( size_t  index){
if (index< _DeviceList.size())
return _DeviceList [index];
return NULL;
}


引用:

好的,所以pasztorpisti的原始解决方案是对的。问题是我试图听取Kenneth的建议并消除指向指针解决方案的指针但发现在这种情况下实际上是正确的解决方案。当只传递WebCamDevice *时,指针本身正在按值传递,所以我无法重新分配它是整个目标。整个问题就像pasztorpisti的例子我应该取消引用指针并分配存储在向量中的指针。所以是的,有些情况下需要指向指针的指针。事实上,我正在使用的许多Window的API都完全相同,例如ActivateObject和MFCreateSourceReaderFromMediaSource。传递对指针的引用可能有效但指针需要初始化为NULL,否则您会收到警告。再次感谢pasztorpisti你对我的愚蠢错误的分析是正确的。唯一的事情是我不想传播**或*&解决方案不正确,因为在这种情况下它是正确的。任何其他解决方案都不符合我的要求或要求我创建和管理不必要的结构或其他类。



最终解决方案如下所示。



 WebCamDevice * tDevice = NULL; 
deviceList-> GetDevice(index,& tDevice);
// ((WebCamVideoConfig *)(device-> VideoConfig) - > WebCamVideoConfig :: SetWidth( ()(tDevice-> GetFriendlyName()!= NULL){
SendMessage(mainWindow) - > DeviceListBox,LB_ADDSTRING, 0 ,(LPARAM)tDevice-> GetFriendlyName());
}

HRESULT WebCamDeviceList :: GetDevice(size_t index,WebCamDevice ** lDevice){
HRESULT hr = S_OK;
WebCamDevice * cDevice = NULL;
if (index < _DeviceList.size()){
* lDevice = _DeviceList [index];
}
返回 hr;
}


Hi guys! After 13 years of losing my real programming skills by getting sucked into Java I've decided to dive back into C++. I wrote a small program to read from a webcam and display the output and now I'm going back and trying to make a framework out of this application. I have one method that just is not working how I would expect and I'm sure the experts here can help.

Here is what I have. This method interrogates the device driver to extract information about a device and builds an object that stores this information then places that object in a vector. This seems to work fine.

HRESULT WebCamDeviceList::RegisterDevice(UINT32 index, IMFActivate* vDevice,  IMFMediaSource* vMediaSource, IMFSourceReader* vMediaReader) {
	HRESULT hr = S_OK;
	LPWSTR dFriendlyName = NULL;
	UINT32 dName = NULL;
         //dFriendlyName returns allocated memory and will need to be cleaned up as some
         //point
	hr = vDevice[index].GetAllocatedString(MF_DEVSOURCE_ATTRIBUTE_FRIENDLY_NAME, &dFriendlyName, &dName);

	if(SUCCEEDED(hr)) {
		WebCamDevice* wDevice = new WebCamDevice();

		wDevice->SetIndex(index);
		wDevice->SetName(dName);
		wDevice->SetFriendlyName(dFriendlyName);

		wDevice->LoadConfiguration(vMediaSource, vMediaReader);

		_DeviceList.push_back(wDevice);

	} else {
		MessageBox(NULL,TEXT("Unable to retieve device name"), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
	}


	return hr;
}



This piece of code retrieves that object pointer from the vector and passes it back to the caller. Using the debugger the retrieval of the object pointer seems to work fine. The problem is that the "device" parameter is passed back with no values almost like it went out of scope and if it was Java I would assume the GCer got it.


HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice** device) {
	HRESULT hr = S_OK;
	WebCamDevice* cDevice = NULL;
	if (index < _DeviceList.size()) {
	  cDevice = _DeviceList[index];
	}
	device = &cDevice;
	return hr;
}




If this helps here is the caller. The line "deviceList->GetDevice(index, &device)" passes back a empty object even though right before it exits I can see the pointer is valid with the debugger.

WebCamDeviceList* deviceList = new WebCamDeviceList();
deviceList->LoadDevices();
deviceList->GetCount(&numberDevices);

size_t index = 0;

mainWindow = new GuiMain(hWnd,hInstance);
while( index < numberDevices ) {
    //MessageBox(NULL,TEXT("Device One" ), TEXT("Error!"), MB_ICONEXCLAMATION | MB_OK);
     WebCamDevice* device = NULL;
     deviceList->GetDevice(index, &device);
    //((WebCamVideoConfig*)(device->VideoConfig)->WebCamVideoConfig::SetWidth(width);
     if(device->GetFriendlyName() != NULL) {
         SendMessage(mainWindow->DeviceListBox, LB_ADDSTRING, 0, (LPARAM)device->GetFriendlyName());
     }
    index++;
}



This has to be something very simple and I feel like a fool not understanding what is going on since I used to do this for a living but Java has destroyed my pointer and memory management skills.

Thank you in advance for any help.
Kevin

解决方案

EDIT: This is the buggy code without modifications:

HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice** device) {
    HRESULT hr = S_OK;
    WebCamDevice* cDevice = NULL;
    if (index < _DeviceList.size()) {
      cDevice = _DeviceList[index];
    }
    device = &cDevice;
    return hr;
}


The function parameters in C/C++ work just like local variables (same is true for java, there is no magic here). With device = &cDevice; you set the value of a pointer local variable. I guess you wanted to do *device = cDevice; or device[0] = cDevice; that has the same effect. Or, if we are talking about C++ and not C I would write:

HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice*& device) {
    device = index < _DeviceList.size() ? _DeviceList[index] : (WebCamDevice*)NULL;
    return S_OK;
}


and
deviceList->GetDevice(index, device);
instead of
deviceList->GetDevice(index, &device);

EDIT: In C++ use reference instead of pointer if it can not be NULL. This isn't only being fancy, it helps you to avoid bugs like this and its also documentation. If someone takes a look at your function/method declaration she will immediately know that the reference parameter can not be NULL while a "double pointer" or "pointer pointer" is always ambiguous. The more "pointer pointers" and "pointer pointer pointers" you use the uglier you code gets. In C++ if you write nice code you rarely need multiple pointer indirections.

EDIT: Since you are always returning S_OK you could simply change your function into this:

WebCamDevice* WebCamDeviceList::GetDevice(size_t index) {
    return index < _DeviceList.size() ? _DeviceList[index] : (WebCamDevice*)NULL;
}


or this that is the same but is easier to place breakpoint into the branches:

WebCamDevice* WebCamDeviceList::GetDevice(size_t index) {
    if (index < _DeviceList.size())
        return _DeviceList[index];
    return NULL;
}


Quote:

Ok so pasztorpisti's original solution was correct. The problem was that I tried to listen to "Kenneth's" suggestion and eliminate the pointer to pointer solution but found out that is actually the proper solution in this case. When passing just WebCamDevice* the pointer itself was being passed by value so I couldn't reassign it which was the entire goal. The entire problem was like pasztorpisti's example I should have been de-referencing the pointer and assigning the pointer stored in the vector. So yes there are cases where a pointer to a pointer is required. Matter of fact many of the Window's APIs I'm using do that exact same thing such as "ActivateObject" and "MFCreateSourceReaderFromMediaSource". Passing a reference to the pointer might have worked but the pointer needs to be initialized to NULL else you receive a warning. Once again thank you pasztorpisti your analysis of my stupid mistake was correct. The only thing is I don't want to propagate that the ** or *& solution is not correct because in this case its is the correct one. Any other solution wouldn't have met my requirement or required me to create and manage a needless struct or another class.

The final solution looks like this.

WebCamDevice* tDevice = NULL;
 deviceList->GetDevice(index, &tDevice);
//((WebCamVideoConfig*)(device->VideoConfig)->WebCamVideoConfig::SetWidth(width);

 if(tDevice->GetFriendlyName() != NULL) {
     SendMessage(mainWindow->DeviceListBox, LB_ADDSTRING, 0, (LPARAM)tDevice->GetFriendlyName());
 }

HRESULT WebCamDeviceList::GetDevice(size_t index, WebCamDevice** lDevice) {
	HRESULT hr = S_OK;
	WebCamDevice* cDevice = NULL;
	if (index < _DeviceList.size()) {
	  *lDevice = _DeviceList[index];
	}
	return hr;
}


这篇关于传回从向量中检索的指针的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆