std::vector‹std::ofstream›::erase выдает ошибку компиляции

Привет, я пытаюсь выполнить некоторые операции с файлами, и при необходимости пользователь может открыть несколько файлов. Я создал производный вектор ofstream, но когда я хочу стереть i. элемент (который файл был закрыт) с компилятором std::vector<Type>::erase(std::vector<Type>::iterator) дает мне ошибку, но у меня есть другой вектор, полученный из std::string, и я стираю его так же, как он не дает ошибки. Мои коды;

#include <iostream>
#include <fstream>
#include <vector>

std::vector<std::ofstream> of;
std::vector<std::string> sv;

int CloseFile(int id, file_t ft) {
    std::vector<std::ofstream>::iterator i;
    std::vector<std::string>::iterator j;
    if (of[id].is_open() == true) {
        of[id].close();
        i = of.begin() + id;
        j = sv.begin() + id;
        of.erase(i); // showing error for this line
        sv.erase(j);
    }
}

Я использую Nsight Eclipse Edition 6.0 в Ubuntu 12.04, и мне все равно нужен открытый файл или файлы, ошибки из раздела «Проблема» выходных данных eclipse;

  1. требуется от ‘_OI std::__copy_move_a(_II, _II, _OI) [с логическим значением _IsMove = false; _II = std::basic_ofstream; _OI = std::basic_ofstream]
  2. требуется от ‘_OI std::__copy_move_a2(_II, _II, _OI) [с логическим значением _IsMove = false; _II = __gnu_cxx::__normal_iterator*, std::vector > >; _OI = __gnu_cxx::__normal_iterator*, std::vector > >]
  3. требуется от ‘_OI std::copy(_II, _II, _OI) [с _II = __gnu_cxx::__normal_iterator*, std::vector > >; _OI = __gnu_cxx::__normal_iterator*, std::vector > >]
  4. требуется от ‘_OI std::copy(_II, _II, _OI) [с _II = __gnu_cxx::__normal_iterator*, std::vector > >; _OI = __gnu_cxx::__normal_iterator*, std::vector > >]
  5. std::basic_streambuf‹_CharT, _Traits>& std::basic_streambuf‹_CharT, _Traits>::operator=(const std::basic_streambuf‹_CharT, _Traits>&) [с _CharT = char; _Traits = std::char_traits]
  6. std::ios_base& std::ios_base::operator=(const std::ios_base&)
  7. make: *** [dosya/dosya.o] Ошибка 1
  8. в этом содержании
  9. в этом содержании
  10. требуется отсюда

Последняя ошибка, указывающая на строку кода

Вывод компилятора: (Некоторые слова на турецком языке, dosya = файл, GeriDonus_t = Return_t, DosyaKapat = FileClose)

16:06:56 **** Incremental Build of configuration Debug for project deneme ****`
make all`
Building file: ../dosya/dosya.cpp`
Invoking: NVCC Compiler`
/usr/local/cuda-6.0/bin/nvcc -I"/usr/local/cuda-6.0/samples/3_Imaging" -I"/usr/local    /cuda-6.0/samples/common/inc" -I"/opt/Calismalar/Cuda/cuda-workspace/deneme" -I/usr/local/opencv/include -I/usr/local/opencv/include/opencv -I/opt/Calismalar/Cuda/cuda-workspace/deneme/ -G -g -O0 -gencode arch=compute_30,code=sm_30 -gencode arch=compute_32,code=sm_32  -odir "dosya" -M -o "dosya/dosya.d" "../dosya/dosya.cpp"`
nvcc warning : The 'compute_10' and 'sm_10' architectures are deprecated, and may be removed in a future release.`
/usr/local/cuda-6.0/bin/nvcc -I"/usr/local/cuda-6.0/samples/3_Imaging" -I"/usr/local/cuda-6.0/samples/common/inc" -I"/opt/Calismalar/Cuda/cuda-workspace/deneme" -I/usr/local/opencv/include -I/usr/local/opencv/include/opencv -I/opt/Calismalar/Cuda/cuda-workspace/deneme/ -G -g -O0 --compile  -x c++ -o  "dosya/dosya.o" "../dosya/dosya.cpp"
In file included from /usr/include/c++/4.8/ios:42:0,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from ../dosya/dosya.h:13,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/bits/basic_ios.h: In instantiation of ‘static _OI std::__copy_move<false, false, std::random_access_iterator_tag>::__copy_m(_II, _II, _OI) [with _II = std::basic_ofstream<char>*; _OI = std::basic_ofstream<char>*]’:
/usr/include/c++/4.8/bits/stl_algobase.h:390:70:   required from ‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = std::basic_ofstream<char>*; _OI = std::basic_ofstream<char>*]’
/usr/include/c++/4.8/bits/stl_algobase.h:428:38:   required from ‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = __gnu_cxx::__normal_iterator<std::basic_ofstream<char>*, std::vector<std::basic_ofstream<char> > >; _OI = __gnu_cxx::__normal_iterator<std::basic_ofstream<char>*, std::vector<std::basic_ofstream<char> > >]’
/usr/include/c++/4.8/bits/stl_algobase.h:460:17:   required from ‘_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator<std::basic_ofstream<char>*, std::vector<std::basic_ofstream<char> > >; _OI = __gnu_cxx::__normal_iterator<std::basic_ofstream<char>*, std::vector<std::basic_ofstream<char> > >]’
/usr/include/c++/4.8/bits/vector.tcc:138:2:   required from ‘std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = std::basic_ofstream<char>; _Alloc = std::allocator<std::basic_ofstream<char> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<std::basic_ofstream<char>*, std::vector<std::basic_ofstream<char> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = std::basic_ofstream<char>*]’
../dosya/dosya.cpp:152:27:   required from here
/usr/include/c++/4.8/bits/ios_base.h:789:5: error: ‘std::ios_base& std::ios_base::operator=(const std::ios_base&)’ is private
     operator=(const ios_base&);
     ^
In file included from /usr/include/c++/4.8/ios:44:0,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from ../dosya/dosya.h:13,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/bits/basic_ios.h:66:11: error: within this context
     class basic_ios : public ios_base
           ^
In file included from /usr/include/c++/4.8/iostream:39:0,
                 from ../dosya/dosya.h:13,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/ostream:58:11: note: synthesized method ‘std::basic_ios<char>& std::basic_ios<char>::operator=(const std::basic_ios<char>&)’ first required here 
     class basic_ostream : virtual public basic_ios<_CharT, _Traits>
           ^
In file included from ../dosya/dosya.h:14:0,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/fstream:599:11: note: synthesized method ‘std::basic_ostream<char>& std::basic_ostream<char>::operator=(const std::basic_ostream<char>&)’ first required here 
     class basic_ofstream : public basic_ostream<_CharT,_Traits>
           ^
In file included from /usr/include/c++/4.8/ios:43:0,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from ../dosya/dosya.h:13,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/streambuf:810:7: error: ‘std::basic_streambuf<_CharT, _Traits>& std::basic_streambuf<_CharT, _Traits>::operator=(const std::basic_streambuf<_CharT, _Traits>&) [with _CharT = char; _Traits = std::char_traits<char>]’ is private
       operator=(const basic_streambuf&) { return *this; };
       ^
In file included from ../dosya/dosya.h:14:0,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/fstream:72:11: error: within this context
     class basic_filebuf : public basic_streambuf<_CharT, _Traits>
           ^
/usr/include/c++/4.8/fstream:599:11: note: synthesized method ‘std::basic_filebuf<char>& >std::basic_filebuf<char>::operator=(const std::basic_filebuf<char>&)’ first required here 
     class basic_ofstream : public basic_ostream<_CharT,_Traits>
           ^
In file included from /usr/include/c++/4.8/bits/char_traits.h:39:0,
                 from /usr/include/c++/4.8/ios:40,
                 from /usr/include/c++/4.8/ostream:38,
                 from /usr/include/c++/4.8/iostream:39,
                 from ../dosya/dosya.h:13,
                 from ../dosya/dosya.cpp:9:
/usr/include/c++/4.8/bits/stl_algobase.h:335:18: note: synthesized method ‘std::basic_ofstream<char>& std::basic_ofstream<char>::operator=(const std::basic_ofstream<char>&)’ first required here 
        *__result = *__first;
                  ^
make: *** [dosya/dosya.o] Error 1

16:06:57 Build Finished (took 456ms)`

Я понятия не имею об этом. Я также просмотрел это, это, это, это (речь идет об ошибке), Часто задаваемые вопросы - q7.1, this (о списке, но ошибка такая же, и я говорю, что ошибка на самом деле не ошибка, и я не менял компилятор (nvcc)). Всем спасибо.


person Orkun Kasapoglu    schedule 07.11.2014    source источник
comment
std::ofstreams не могут быть скопированы. Вам нужно использовать указатели.   -  person molbdnilo    schedule 07.11.2014
comment
@molbdnilo, спасибо   -  person Orkun Kasapoglu    schedule 07.11.2014
comment
Почему std::vector использует operator= для добавления или удаления? Разве это не сделано с очередью указателей или стеком и использовать free(void*) после удаления элемента? Речь идет о стандартных определениях С++ 11?   -  person Orkun Kasapoglu    schedule 07.11.2014
comment
Я изменил определение вектора на std::vector<std::ofstream*> of;, и теперь ошибки нет, но я еще не пробовал. Спасибо всем еще раз.   -  person Orkun Kasapoglu    schedule 07.11.2014
comment
Предложение vector<unique_ptr<ostream>>   -  person Neil Kirk    schedule 07.11.2014


Ответы (3)


std::vector хранит свои элементы в непрерывном блоке памяти без промежутков. Чтобы стереть элемент, все элементы позади будут перемещены или скопированы на новые позиции. std::ofstream в этом случае не может быть перемещен, поэтому он работает с ошибкой компиляции.

Не используйте std::ofstream непосредственно в std::vector. Он работает со ссылками, указателями или — я предпочитаю — std::unique_ptr.

Он также работает с std::list вместо вектора. std::list имеет другой способ хранения своих элементов, он не перемещает их. Но я не уверен, что это лучше, чем reference/pinter/std_unique_ptr в std:vector.

person Tunichtgut    schedule 07.11.2014
comment
Этот ответ верен для С++ 98/03 и неверен для С++ 11/14. - person Howard Hinnant; 07.11.2014
comment
Как я ответил, это не работает в этом случае. Это может быть в С++ 11/14, но в худшем случае это вызывает огромное количество ходов (~ n * (n-1)/2), если вы начинаете стирать каждый элемент спереди. Чтобы получить эффективный код - не делайте этого, даже если он работает. - person Tunichtgut; 07.11.2014
comment
@Tunichtgut: вектор часто является наиболее эффективным выбором для небольших коллекций, какой бы неприятной ни казалась его асимптотическая сложность. Часто n должен быть довольно большим, прежде чем он станет менее эффективным, чем (теоретически) более эффективные альтернативы. - person Mike Seymour; 07.11.2014
comment
Верно, но попробуй с потоком. std:vector, std::deque и std::list, каждый из 10 элементов, но без открытого файла. Создавать и останавливать время только для очистки контейнера ('x.erase(x.begin())' работает для всех трех). Накопив более 10000 прогонов, я получил 0,021 с для списка, 0,017 с для очереди и 0,034 с для вектора для удаления элементов. Изменено на 100 элементов, время составляет 0,249 с для списка, 0,166 с для очереди и 2,811 с ​​для вектора. При 10 элементах вектор является чуть менее эффективным контейнером. При 100 элементах вектор полностью превосходит число. (ВК2013, выпуск) - person Tunichtgut; 10.11.2014

Gcc-4.8 не поддерживает движущиеся потоки. В этом отношении ваш код соответствует С++ 11, а ваша реализация - нет.

person Howard Hinnant    schedule 07.11.2014
comment
да, я знаю, и он не будет компилироваться или запускаться. Я использую турецкие слова для имен переменных, и я хотел, чтобы коды были более удобочитаемыми для всех. Сейчас редактирую извините. - person Orkun Kasapoglu; 07.11.2014
comment
Вы знаете, основан ли nvcc на gcc 4.8 или нет? Потому что, если код соответствует C++11, nvcc на основе Gcc 4.8 или Nsight Eclipse Edition не совместим с C++11, я ошибаюсь? - person Orkun Kasapoglu; 07.11.2014

Я изменил код, и теперь он не имеет ошибок. Спасибо всем.

Теперь есть:

#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>

std::vector<std::ofstream*> of;
std::vector<std::string> sv;

int CloseFile(int id, file_t ft) {
    std::vector<std::ofstream*>::iterator i;
    std::vector<std::string>::iterator j;
    if (of[id]->is_open() == true) {
        of[id]->close();
        i = of.begin() + id;
        j = sv.begin() + id;
        free(of[id]);
        of.erase(i);
        sv.erase(j);
    }
}

но я еще не пробовал. Просто сейчас нет ошибки компилятора.

person Orkun Kasapoglu    schedule 07.11.2014
comment
-1 это похоже на утечку памяти... В других ответах советовали избегать vector::earse(). - person Walter; 07.11.2014
comment
@Walter, спасибо, но почему происходит утечка памяти? если файл не был открыт, значит, память еще не выделена. - person Orkun Kasapoglu; 07.11.2014