因此,如果我在程序退出时使用下面的代码,我会在此位置的std :: list中获得异常。这与我是否添加项目无关。
void clear() _NOEXCEPT
{ // erase all
#if _ITERATOR_DEBUG_LEVEL == 2
this->_Orphan_ptr(*this, nullptr);
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
_Nodeptr _Pnode = this->_Nextnode(this->_Myhead);
this->_Nextnode(this->_Myhead) = this->_Myhead;
this->_Prevnode(this->_Myhead) = this->_Myhead;
this->_Mysize = 0;
for (_Nodeptr _Pnext; _Pnode != this->_Myhead; _Pnode = _Pnext)
{ // delete an element
_Pnext = this->_Nextnode(_Pnode); //Unhandled exception, access violation
this->_Freenode(_Pnode);
}
}
这是我目前使用std :: list的唯一容器,我只有1个... 如果我将std :: list切换到std :: vector,那么它可以正常工作。
#pragma once
#ifndef EVENT_H
#define EVENT_H
#include <delegate.h>
#include <list>
#include <vector>
using fd::delegate;
template<typename... Args>
class Event;
template<typename...Args>
class Event<void(Args...)>
{
private:
std::list<delegate<void(Args...)>> m_delegates;
public:
void addListener(const delegate<void(Args...)>& d)
{
if (d)
m_delegates.push_back(d);
}
void removeListener(const delegate<void(Args...)>& d)
{
if (d)
m_delegates.remove(d);
}
void removeDeadListeners()
{
for (auto i = m_delegates.begin(); i != m_delegates.end(); i++)
{
if (i->empty())
m_delegates.remove(i);
}
}
void operator()(Args... args)
{
for (auto& d : m_delegates)
{
d(args...);
}
}
};
#endif //EVENT_H
任何使用std :: list的方法?
答案 0 :(得分:3)
我相信你的问题是你在迭代它时会从list
中移除项目,但我很惊讶你所编写的代码完全可以编译。
for (auto i = m_delegates.begin(); i != m_delegates.end(); i++)
{
if (i->empty())
m_delegates.remove(i); // <-- This shouldn't compile
}
list::remove
以list::value_type
为参数,而不是list::iterator
,因此上述内容无法编译。解决方案是使用list::erase
for (auto i = m_delegates.begin(); i != m_delegates.end(); )
{
if (i->empty())
i = m_delegates.erase(i); // get iterator to next element
else
++i;
}
您还可以完全消除循环并使用list::remove_if
m_delegates.remove_if([](decltype(m_delegates)::value_type const& elem) {
return elem.empty();
});
答案 1 :(得分:0)
我已经确定它只是与它声明的类有关,因为我可以在其他类中使用Event .....我只是困惑因为我从不调用单个方法。我只是修改一个教程代码,以便更轻松地使用我的测试项目。默认构造函数适用于其他类,我可以添加/调用方法,这只是这个......我很难过。
.h
#pragma once
#ifndef D3DAPP_H
#define D3DAPP_H
#pragma warning(push)
#pragma warning( disable : 4005) //Ignore Identical Macro declarations that exist in Windows and DirectX headers
#include <D3D11.h>
#include <D3DX11.h>
#include <Windows.h>
#pragma warning(pop)
#include "GameTimer.h"
#include <string>
#include "Event.h"
class D3DApp
{
public:
D3DApp(HINSTANCE hInstance);
virtual ~D3DApp();
HINSTANCE AppInst() const;
HWND MainWnd() const;
float AspectRatio() const;
int Run();
/*
Framework methods. Derived client class overrides these methods
to implement specific application requirements
*/
virtual bool Init();
virtual void Release();
Event<void(int,int)> OnResize;
virtual void UpdateScene(float dt) = 0;
virtual void DrawScene() = 0;
virtual LRESULT MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
//Convenience overrides for handling mouse input
virtual void OnMouseDown(WPARAM btnState, int x, int y);
virtual void OnMouseUp(WPARAM btnState, int x, int y);
virtual void OnMouseMove(WPARAM btnState, int x, int y);
protected:
virtual void ApplicationResize(int w, int h);
bool InitMainWindow();
bool InitDirect3D();
void CalculateFrameStats();
protected:
HINSTANCE mAppInstance;
HWND mMainWnd;
bool mAppPaused;
bool mMinimized;
bool mMaximized;
bool mResizing;
bool mInitialized;
UINT m4xMsaaQuality;
GameTimer mTimer;
ID3D11Device* md3dDevice;
ID3D11DeviceContext* md3dImmediateContext;
IDXGISwapChain* mSwapChain;
ID3D11Texture2D* mDepthStencilBuffer;
ID3D11RenderTargetView* mRenderTargetView;
ID3D11DepthStencilView* mDepthStencilView;
D3D11_VIEWPORT mScreenViewport;
std::wstring mMainWndCaption;
D3D_DRIVER_TYPE md3dDriverType;
int mClientWidth;
int mClientHeight;
bool mEnable4xMsaa;
};
#endif //D3DAPP_H
.cpp
#include "d3dApp.h"
#include "Utility.h"
#include <assert.h>
#include <sstream>
D3DApp* g_d3dApp = 0;
LRESULT CALLBACK
MainWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
return g_d3dApp->MsgProc(hwnd, msg, wParam,lParam);
}
D3DApp::D3DApp(HINSTANCE hInstance)
: mAppInstance(hInstance),
mMainWndCaption(L"D3D11 Application"),
md3dDriverType(D3D_DRIVER_TYPE_HARDWARE),
mClientWidth(800),
mClientHeight(600),
mEnable4xMsaa(false),
mMainWnd(0),
mAppPaused(false),
mMinimized(false),
mMaximized(false),
mResizing(false),
mInitialized(false),
m4xMsaaQuality(0),
md3dDevice(0),
md3dImmediateContext(0),
mSwapChain(0),
mDepthStencilBuffer(0),
mRenderTargetView(0),
mDepthStencilView(0)
{
ZeroMemory(&mScreenViewport, sizeof(D3D11_VIEWPORT));
g_d3dApp = this;
}
void D3DApp::Release()
{
ReleaseCOM(mRenderTargetView);
ReleaseCOM(mDepthStencilView);
ReleaseCOM(mSwapChain);
ReleaseCOM(mDepthStencilBuffer);
if (md3dImmediateContext)
md3dImmediateContext->ClearState();
ReleaseCOM(md3dImmediateContext);
ReleaseCOM(md3dDevice);
if (g_d3dApp == this)
g_d3dApp = nullptr;
mInitialized = false;
}
D3DApp::~D3DApp()
{
if (mInitialized) Release();
}
float D3DApp::AspectRatio() const
{
return static_cast<float>(mClientWidth) / mClientHeight;
}
int D3DApp::Run()
{
MSG msg = { 0 };
mTimer.Reset();
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
mTimer.Tick();
CalculateFrameStats();
UpdateScene(mTimer.DeltaTime());
DrawScene();
}
}
return (int)msg.wParam;
}
bool D3DApp::Init()
{
if (!InitMainWindow())
return false;
if (!InitDirect3D())
return false;
mInitialized = true;
return true;
}
void D3DApp::ApplicationResize(int w,int h)
{
assert(md3dImmediateContext);
assert(md3dDevice);
assert(mSwapChain);
ReleaseCOM(mRenderTargetView);
ReleaseCOM(mDepthStencilView);
ReleaseCOM(mDepthStencilBuffer);
mClientWidth = w;
mClientHeight = h;
HR(mSwapChain->ResizeBuffers(1, mClientWidth, mClientHeight, DXGI_FORMAT_R8G8B8A8_UNORM, 0));
ID3D11Texture2D* backBuffer;
HR(mSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBuffer)));
HR(md3dDevice->CreateRenderTargetView(backBuffer, 0, &mRenderTargetView));
ReleaseCOM(backBuffer);
D3D11_TEXTURE2D_DESC depthStencilDesc;
ZeroMemory(&depthStencilDesc, sizeof(D3D11_TEXTURE2D_DESC));
depthStencilDesc.Width = mClientWidth;
depthStencilDesc.Height = mClientHeight;
depthStencilDesc.MipLevels = 1;
depthStencilDesc.ArraySize = 1;
depthStencilDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
if (mEnable4xMsaa)
{
depthStencilDesc.SampleDesc.Count = 4;
depthStencilDesc.SampleDesc.Quality = m4xMsaaQuality - 1;
} //No MSAA
else
{
depthStencilDesc.SampleDesc.Count = 1;
depthStencilDesc.SampleDesc.Quality = 0;
}
depthStencilDesc.Usage = D3D11_USAGE_DEFAULT;
depthStencilDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilDesc.CPUAccessFlags = 0;
depthStencilDesc.MipLevels = 0;
HR(md3dDevice->CreateTexture2D(&depthStencilDesc, 0, &mDepthStencilBuffer));
HR(md3dDevice->CreateDepthStencilView(mDepthStencilBuffer, 0, &mDepthStencilView));
md3dImmediateContext->OMSetRenderTargets(1, &mRenderTargetView,mDepthStencilView);
mScreenViewport.TopLeftX = 0;
mScreenViewport.TopLeftY = 0;
mScreenViewport.Width = static_cast<float>(mClientWidth);
mScreenViewport.Height = static_cast<float>(mClientWidth);
mScreenViewport.MinDepth = 0.0f;
mScreenViewport.MaxDepth = 1.0f;
md3dImmediateContext->RSSetViewports(1, &mScreenViewport);
//OnResize(w, h);
}
LRESULT D3DApp::MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
//Ignore messages until we have intialized everything
if (!mInitialized)
return DefWindowProc(hWnd, msg, wParam, lParam);
switch (msg)
{
case WM_ACTIVATE:
if (LOWORD(wParam) == WA_INACTIVE)
{
mAppPaused = true;
mTimer.Stop();
}
else
{
mAppPaused = false;
mTimer.Start();
}
return 0;
case WM_SIZE:
if (wParam == SIZE_MINIMIZED)
{
mAppPaused = true;
mMinimized = true;
mMaximized = false;
mTimer.Stop();
}
else if (wParam == SIZE_MAXIMIZED)
{
mAppPaused = SIZE_MAXIMIZED;
mMinimized = false;
mMaximized = true;
ApplicationResize(LOWORD(lParam), HIWORD(lParam));
}
else if (wParam == SIZE_RESTORED)
{
if (mMinimized)
{
mAppPaused = false;
mMinimized = false;
mTimer.Start();
ApplicationResize(LOWORD(lParam), HIWORD(lParam));
}
else if (mMaximized)
{
mAppPaused = false;
mMaximized = false;
ApplicationResize(LOWORD(lParam), HIWORD(lParam));
}
else if (mResizing)
{
//We don't want to do stuff while this is going on
}
else
{
ApplicationResize(LOWORD(lParam), HIWORD(lParam));
}
}
return 0;
case WM_ENTERSIZEMOVE:
mAppPaused = true;
mResizing = true;
mTimer.Stop();
return 0;
case WM_EXITSIZEMOVE:
mAppPaused = false;
mResizing = false;
mTimer.Start();
if (lParam != 0)
ApplicationResize(LOWORD(lParam), HIWORD(lParam));
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_MENUCHAR:
//Don't beep when we alt-enter
return MAKELRESULT(0, MNC_CLOSE);
case WM_GETMINMAXINFO:
((MINMAXINFO*)lParam)->ptMinTrackSize.x = 200;
((MINMAXINFO*)lParam)->ptMinTrackSize.y = 200;
return 0;
case WM_LBUTTONDOWN:
case WM_MBUTTONDOWN:
case WM_RBUTTONDOWN:
OnMouseDown(wParam, LOWORD(lParam), HIWORD(lParam));
return 0;
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
OnMouseUp(wParam, LOWORD(lParam), HIWORD(lParam));
return 0;
case WM_MOUSEMOVE:
OnMouseMove(wParam, LOWORD(lParam), HIWORD(lParam));
return 0;
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
bool D3DApp::InitMainWindow()
{
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = mAppInstance;
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
wc.hCursor = LoadCursor(0, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(NULL_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"D3DWndClassName";
if (!RegisterClass(&wc))
{
MessageBox(0, L"RegisterClass Failed!", 0, 0);
return false;
}
RECT R = { 0, 0, mClientWidth, mClientHeight };
AdjustWindowRect(&R, WS_OVERLAPPEDWINDOW, false);
int width = R.right - R.left;
int height = R.bottom - R.top;
mMainWnd = CreateWindow(L"D3DWndClassName", mMainWndCaption.c_str(),
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, width, height, 0, 0, mAppInstance, 0);
if (mMainWnd);
{
MessageBox(0, L"CreateWindow Failed", 0, 0);
return false;
}
ShowWindow(mMainWnd, SW_SHOW);
UpdateWindow(mMainWnd);
return true;
}
bool D3DApp::InitDirect3D()
{
//Create the device and device context
UINT createDeviceFlags = 0;
#if defined(DEBUG) || defined(_DEBUG)
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL featureLevel;
HRESULT hr = D3D11CreateDevice(
0,
md3dDriverType,
0,
createDeviceFlags,
0, 0,
D3D11_SDK_VERSION,
&md3dDevice,
&featureLevel,
&md3dImmediateContext);
if (FAILED(hr))
{
MessageBox(0, L"D3D11CreateDevice Failed.", 0, 0);
return false;
}
if (featureLevel != D3D_FEATURE_LEVEL_11_0)
{
MessageBox(0, L"Direct3D Feature Level 11 unsupported", 0, 0);
return false;
}
HR(md3dDevice->CheckMultisampleQualityLevels(
DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality));
assert(m4xMsaaQuality > 0);
DXGI_SWAP_CHAIN_DESC sd;
sd.BufferDesc.Width = mClientWidth;
sd.BufferDesc.Height = mClientHeight;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
sd.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
if (mEnable4xMsaa)
{
sd.SampleDesc.Count = 4;
sd.SampleDesc.Quality = m4xMsaaQuality - 1;
}
else
{
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
}
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.BufferCount = 1;
sd.OutputWindow = mMainWnd;
sd.Windowed = true;
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
sd.Flags = 0;
IDXGIDevice* dxgiDevice = 0;
HR(md3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice));
IDXGIAdapter* dxgiAdapter = 0;
HR(dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&dxgiAdapter));
IDXGIFactory* dxgiFactory = 0;
HR(dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)&dxgiFactory));
HR(dxgiFactory->CreateSwapChain(md3dDevice, &sd, &mSwapChain));
ReleaseCOM(dxgiDevice);
ReleaseCOM(dxgiAdapter);
ReleaseCOM(dxgiFactory);
ApplicationResize(mClientWidth, mClientHeight);
return true;
}
void D3DApp::CalculateFrameStats()
{
//Code computes the average frames per second also the average
//time it takes to render one frame. These stats
//are appended to the window caption bar.
static int frameCnt = 0;
static float timeElapsed = 0.0f;
frameCnt++;
float dt = mTimer.TotalTime() - timeElapsed;
if (dt >= 1.0f)
{
float fps = (float)frameCnt/dt;
float mspf = 1000.0f / fps;
std::wstringstream outs;
outs.precision(6);
outs << mMainWndCaption << L" "
<< L"FPS: " << fps << L" "
<< L"Frame Time: " << mspf << L" (ms)";
SetWindowText(mMainWnd, outs.str().c_str());
frameCnt = 0;
timeElapsed += dt;
}
}
void D3DApp::OnMouseDown(WPARAM btnState, int x, int y)
{
}
void D3DApp::OnMouseUp(WPARAM btnState, int x, int y)
{
}
void D3DApp::OnMouseMove(WPARAM btnState, int x, int y)
{
}