std::vector Неуспешно твърдение (векторните итератори са несъвместими)

Имам тази структура:

struct MxMInstanceData
{
    D3DXVECTOR2 mTransform;
    float mSpacing;
};

След това създавам вектор на MxMInstanceData:

std::vector<MxMInstanceData> instInFrustumData;

Ако извикам instInFrustumData.clear(), получавам тази грешка:

Твърдението е неуспешно (векторните итератори са несъвместими)

Код за създаване на вектор:

instInFrustumData.reserve(mNumInstances);

Векторен код за актуализация:

void Terrain::updateInstances()
{
    mNumInstancesInFrustum = 0;

    if(instInFrustumData.size() != 0)
        instInFrustumData.clear();

    mpMxMInstInFrustumB->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

    for(int x = 0; x < mNumInstances; x++)
    {
        if(mpCamera->point2DInFrustum(instData[x].mTransform + 
            D3DXVECTOR2(instData[x].mSpacing/2 + mpCamera->getPosition().x, instData[x].mSpacing/2 + mpCamera->getPosition().z), instData[x].mSpacing/2)
            != OUTSIDE)
        {
            instInFrustumData.push_back(instData[x]);
            mNumInstancesInFrustum++;
        }
    }

    mpMxMInstInFrustumB->Unmap();
}

Какво може да накара това да се случи?

И в деструктора на моя клас също извиквам clear()


person Tiago Costa    schedule 28.04.2011    source източник
comment
Вашият публикуван код не може - така че публикувайте повече.   -  person Erik    schedule 28.04.2011
comment
Намерих друго нещо: след като създам вектора, го преоразмерявам така, че размер = капацитет. Извиквам clear() и всичко е наред, така че размер = 0 капацитет = 100, след това го запълвам само с 8 стойности и когато извикам clear отново (за втори път), се извежда грешката   -  person Tiago Costa    schedule 28.04.2011
comment
Нещо, което може да направи това да се случи, е взаимозаменяемото използване на константни и неконстантни итератори. Трябва обаче да публикувате действителния си код, защото това, което имате тук, не причинява тази грешка.   -  person AJG85    schedule 28.04.2011
comment
Да, това също е потенциално несвързано, така че трябва просто да публикувате действителния си код, като използвате вектора в пълна форма. Имайте предвид обаче, че трябва да използвате reserve, за да резервирате капацитет във вектор, без да създавате елементи. resize ще премахне елементи или ще разшири вектора и евентуално ще създаде нови празни елементи в зависимост от текущия размер и присъстващите елементи при извикването му.   -  person AJG85    schedule 28.04.2011
comment
Първо използвах резерв, след това промених на преоразмеряване, но грешката продължаваше...   -  person Tiago Costa    schedule 28.04.2011


Отговори (2)


Може да искате да проверите справка за използването на std::vector като http://www.cplusplus.com/reference/stl/vector/ или купете добра STL книга. Вие използвате някои методи по начини, които аз бих сметнал за неортодоксални.

  • Използвайте empty(), за да проверите дали векторът има елементи (ако не е празен, ясно просто се чете по-добре)
  • Използвайте променливи с локален обхват, когато е възможно (нещата, които не трябва да остават в обхвата, не трябва)
  • Използвайте STL итератори или размери на контейнери в цикли (необходими ли са две увеличаващи се цели числа в един цикъл?)
  • Използвайте "най-добрия" STL контейнер за вашата реализация (тук искате вектори или карти?)
  • Избягвайте отливки в стил C и злоупотреба с обекти ((void**) &instInFrustumData е много лоша идея)

Имате толкова много членски променливи, чиято дефиниция е неизвестна, както и неизвестни методи Map() и UnMap() и все още не сте показали никакъв код, използващ итератори, свързани с първоначалната ви грешка. Предполагам, че използването на instData[x] е опасно и проблематично, както и начинът, по който този цикъл е конструиран като цяло. Също така наистина не искате да третирате STL контейнерите като нещо друго освен STL контейнери. Неща като (void**) &instInFrustumData трябва да се избягват, тъй като могат да причинят само проблеми.

Горещо препоръчвам първо да научите C++, преди да се захванете с DirectX или графични и игрови двигатели, написани и на двете.

person AJG85    schedule 28.04.2011
comment

Имам някои VTK-файлове, които изглеждат така:

# vtk DataFile Version 1.0
Line representation of vtk
ASCII
DATASET POLYDATA
POINTS 30 FLOAT
234 462 35
233 463 35
231 464 35
232 464 35
229 465 35
[...]
LINES 120 360
2 0 1
2 0 1
2 1 0
2 1 3
2 1 0
2 1 3
2 2 5
2 2 3
[...]

Бих искал да получа два списъка от тези VTK-файлове: edgesList и verticesList:

  • edgesList трябва да съдържа ръбовете като (FromVerticeIndex, ToVerticeIndex, Weight)-кортежи
  • verticesList трябва да съдържа върховете като (x,y,z)-кортежи. Индексът е индексът, споменат в edgesList

Нямам представа как да извлека това с библиотеката standard-vtk-python. Стигнах дотук:

import sys, vtk

filename = "/home/graphs/g000231.vtk"

reader = vtk.vtkSTLReader()
reader.SetFileName(filename)
reader.Update()

idList = vtk.vtkIdList() 

polyDataOutput = reader.GetOutput()
print polyDataOutput.GetPoints().GetData()

Възможно е моят python-vtk-код да няма смисъл. Бих предпочел да използвам vtk библиотеката и да не използвам самостоятелно написани части от код.

Ето моето самостоятелно написано парче код. Работи, но би било по-добре, ако мога да използвам vtk библиотеката за това:

import re
def readVTKtoGraph(filename):
    """ Specification of VTK-files:
        http://www.vtk.org/VTK/img/file-formats.pdf - page 4 """
    f = open(filename)
    lines = f.readlines()
    f.close()

    verticeList = []
    edgeList = []

    lineNr = 0
    pattern = re.compile('([\d]+) ([\d]+) ([\d]+)')
    while "POINTS" not in lines[lineNr]:
        lineNr += 1

    while "LINES" not in lines[lineNr]:
        lineNr += 1
        m = pattern.match(lines[lineNr])
        if m != None:
            x = float(m.group(1))
            y = float(m.group(2))
            z = float(m.group(3))
            verticeList.append((x,y,z))

    while lineNr < len(lines)-1:
        lineNr += 1
        m = pattern.match(lines[lineNr])
        nrOfPoints = m.group(1)
        vertice1 = int(m.group(2))
        vertice2 = int(m.group(3))
        gewicht = 1.0
        edgeList.append((vertice1, vertice2, gewicht))
    return (verticeList, edgeList)
- person Tiago Costa; 28.04.2011
comment
Това е добре. Изглежда, че иска изходящ параметър на паметта, в който да пише евентуално за изчертаване по-късно. Не е страхотна идея да се излагат вътрешностите на STL вектор, за да се записва директно от нещо, което не е проектирано с мисъл за STL. Ако ТРЯБВА, вероятно бих използвал &instInFrustumData.data(), но честно казано бих предпочел да използвам байтов масив в този случай, след което да попълня вектора си в кода, който контролирам. - person AJG85; 28.04.2011
comment
Току-що потърсих метода ... Map() и Unmap() изглежда са заключващи механизми за буфера. Може да е за предпочитане да използвате нещо повече по линия на boost::mutex и boost::mutex::scoped_lock или някакво друго заключване, базирано на mutex, за контролиране на достъпа за запис във вашия вектор. Ако не, опитайте да използвате &instInFrustumData.data() вместо това, тъй като това всъщност е указател към вътрешния буфер, където е разпределена паметта на вектора. - person AJG85; 28.04.2011
comment
instInFrustumData.data() го поправи, много благодаря :D. Можете ли да ми кажете името на добра STL книга, защото знам само основите на STL... Дори не знаех за съществуването на метода data()... Освен това не съм запознат с boost namespace. Ще си купя и книга за по-напреднал C++, защото този, който имам, е наистина основен, така че дори не знам какво са шаблони и т.н.: S - person Tiago Costa; 28.04.2011
comment
boost.org е доста звездна C++ библиотека на трета страна, толкова добра, че голяма част от нея се приема в новия стандарт C++ и е частично наличен в нова форма под пространството от имена std::tr1. Що се отнася до книгите, бих препоръчал всичко от Скот Майерс или Хърб Сътър за някои наистина добри съвети и трикове, но вижте тази статия за справка: stackoverflow.com/questions/388242/ - person AJG85; 30.04.2011

Донякъде предполагам, но може би вашият проблем е този ред:

mpMxMInstInFrustumB->Map(D3D10_MAP_WRITE_DISCARD, NULL, (void**) &instInFrustumData);

Предавате указател към самия вектор към тази функция Map, която предполагам може да презаписва някои от нейните вътрешни елементи? Нямам документация, но не изглежда като функция, която очаква указател към вектор :)

person Luke Halliwell    schedule 28.04.2011