【问题标题】:std::vector<std::ofstream>::erase is giving compile errorstd::vector<std::ofstream>::erase 给出编译错误
【发布时间】:2015-01-04 08:43:28
【问题描述】:

您好,我正在尝试进行一些文件操作,如果需要,用户可以打开多个文件。我创建了一个派生的矢量ofstream,但是当我想擦除 i 时。带有std::vector&lt;Type&gt;::erase(std::vector&lt;Type&gt;::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);
    }
}

我在 Ubuntu 12.04 上使用 Nsight Eclipse Edition 6.0,无论如何我需要打开一个或多个文件,Eclipse 输出的问题部分的错误是;

  1. 需要从‘_OI std::__copy_move_a(_II, _II, _OI) [with bool _IsMove = false; _II = std::basic_ofstream; _OI = std::basic_ofstream]
  2. 需要从‘_OI std::__copy_move_a2(_II, _II, _OI) [with bool _IsMove = false; _II = __gnu_cxx::__normal_iterator*, std::vector > >; _OI = __gnu_cxx::__normal_iterator*, std::vector > >]
  3. 需要从‘_OI std::copy(_II, _II, _OI) [with _II = __gnu_cxx::__normal_iterator*, std::vector >>; _OI = __gnu_cxx::__normal_iterator*, std::vector > >]
  4. 需要从‘_OI std::copy(_II, _II, _OI) [with _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>&) [with _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 = file,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)`

我不知道。我也看过thisthisthisthis(关于日食bug),FAQ - q7.1,this(关于列表,但错误是一样的,说错误实际上不是错误,我没有更改编译器(nvcc))。谢谢大家。

【问题讨论】:

  • std::ofstreams 无法复制。你需要使用指针。
  • @molbdnilo 谢谢
  • 为什么std::vector 使用operator= 进行添加或删除?是不是已经完成了指针队列或堆栈并在删除元素后使用free(void*)?是关于 c++11 标准定义的吗?
  • 我已将矢量定义更改为std::vector&lt;std::ofstream*&gt; of;,现在没有错误但我还没有尝试过。再次感谢大家。
  • 建议vector&lt;unique_ptr&lt;ostream&gt;&gt;

标签: c++ c++11 stdvector ofstream nsight


【解决方案1】:

我已更改代码,现在没有错误。谢谢大家。

现在是:

#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);
    }
}

但我还没有尝试过。只是现在没有编译错误。

【讨论】:

  • -1 这看起来像内存泄漏......其他答案的建议是避免vector::earse()
  • @Walter 谢谢你,但为什么它会泄漏内存?如果文件没有打开意味着内存还没有分配。
【解决方案2】:

std::vector 将其元素保存在一个连续的内存块中,没有间隙。擦除元素会导致后面的所有元素移动或复制到新位置。在这种情况下,std::ofstream 无法移动,因此会在编译错误中运行。

不要在 std::vector 中直接使用 std::ofstream。它适用于引用、指针或 - 我更喜欢 - std::unique_ptr。

它也适用于 std::list 而不是向量。 std::list 有另一种保存元素的方式,它不会移动它们。但我不确定这是否比 std:vector 中的 reference/pinter/std_unique_ptr 更好。

【讨论】:

  • 这个答案对于 C++98/03 是正确的,对于 C++11/14 是不正确的。
  • 正如我回答的那样,它在这种情况下不起作用。它可能在 C++ 11/14 中,但如果您开始从前面擦除每个元素,它会在最坏的情况下(~ n*(n-1)/2)导致大量移动。为了获得高效的代码 - 即使它有效,也不要这样做。
  • @Tunichtgut:对于小型集合来说,向量通常是最有效的选择,但它的渐近复杂性让人感觉很讨厌。通常,n 必须相当大,才能变得比(理论上)更有效的替代方案效率低。
  • 没错,但请尝试使用 ofstream。一个 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 个元素处,向量总数超过了。 (VC2013,发布)
【解决方案3】:

Gcc-4.8 不支持移动流。您的代码在这方面符合 C++11,只是您的实现不符合。

【讨论】:

  • 是的,我知道,它不会编译或运行。我使用土耳其语作为变量名,我希望代码对每个人都更具可读性。抱歉,我现在正在编辑。
  • 你知道nvcc是不是基于gcc 4.8吗?因为如果代码符合基于 Gcc 4.8 的 C++11 nvcc 或者 Nsight Eclipse Edition 不兼容 C++11,我错了吗?
猜你喜欢
  • 2022-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-03-24
  • 2014-05-12
  • 2015-04-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多