从 linux 到 windows 的 C++:'不计算为常数'

Posted

技术标签:

【中文标题】从 linux 到 windows 的 C++:\'不计算为常数\'【英文标题】:C++ from linux to windows: 'does not evaluate to a constant'从 linux 到 windows 的 C++:'不计算为常数' 【发布时间】:2017-06-15 09:03:42 【问题描述】:

我正在尝试将此功能从 Linux 移植到 Windows:

template<class TDescriptor, class F>
bool TemplatedVocabulary<TDescriptor,F>::loadFromBinaryFile(const std::string &filename) 
  fstream f;
  f.open(filename.c_str(), ios_base::in|ios::binary);
  unsigned int nb_nodes, size_node;
  f.read((char*)&nb_nodes, sizeof(nb_nodes));
  f.read((char*)&size_node, sizeof(size_node));
  f.read((char*)&m_k, sizeof(m_k));
  f.read((char*)&m_L, sizeof(m_L));
  f.read((char*)&m_scoring, sizeof(m_scoring));
  f.read((char*)&m_weighting, sizeof(m_weighting));
  createScoringObject();

  m_words.clear();
  m_words.reserve(pow((double)m_k, (double)m_L + 1));
  m_nodes.clear();
  m_nodes.resize(nb_nodes+1);
  m_nodes[0].id = 0;
  char buf[size_node];// fails

  int nid = 1;
  while (!f.eof()) 
    f.read(buf, size_node);
    m_nodes[nid].id = nid;
    // FIXME
    const int* ptr=(int*)buf;
    m_nodes[nid].parent = *ptr;
    //m_nodes[nid].parent = *(const int*)buf;
    m_nodes[m_nodes[nid].parent].children.push_back(nid);
    m_nodes[nid].descriptor = cv::Mat(1, F::L, CV_8U);
    memcpy(m_nodes[nid].descriptor.data, buf+4, F::L);
    m_nodes[nid].weight = *(float*)(buf+4+F::L);
    if (buf[8+F::L])  // is leaf
      int wid = m_words.size();
      m_words.resize(wid+1);
      m_nodes[nid].word_id = wid;
      m_words[wid] = &m_nodes[nid];
    
    else
      m_nodes[nid].children.reserve(m_k);
    nid+=1;
  
  f.close();
  return true;

这一行:

char buf[size_node];

不会编译,报错:

expression did not evaluate to a constant.

我尝试过使用:

std::vector&lt;char&gt; buf(size_node)

和:

char buf[size_node] = new char[];

但我看到了同样的错误。似乎这与运行时间常数与编译时间常数有关,如此处的答案所述:

Tuple std::get() Not Working for Variable-Defined Constant

但我不确定在这种情况下如何解决它。谢谢。

【问题讨论】:

GCC 支持可变长度数组作为扩展(这是你所拥有的),而标准 C++ 不支持。这就是为什么您应该始终使用-pedantic 构建的原因。我不知道您如何尝试vector,但它应该可以工作。 C++ 没有variable-length arrays。一些编译器将其添加为语言的扩展。请改用std::vector 其他几件事:数组索引是从零开始的size_node 元素的数组(或向量)具有从 0size_node - 1(含)的索引。然后阅读Why is iostream::eof inside a loop condition considered wrong? 另见How do compilers treat variable length arrays和How does GCC implement variable-length arrays? 【参考方案1】:

应该是

char *buf = new char[size_node];

使用后记得删除内存。

或者,只需使用std::vector。它更安全。

std::vector<char> buf(size_node);

那么你必须改变buf 的使用方式。例如:

f.read(buf, size_node);

应该变成

f.read(buf.data(), size_node); //Only C++11

【讨论】:

对于那些不喜欢清理自己的内存分配并且由于某种原因不愿意使用vector的人,你可以做auto buf = std::make_unique&lt;char[]&gt;(size_node);之类的事情,虽然你不能完全对待它就像一个普通的旧数组。 谢谢!完美。 @anti : 如果此答案正确,请标记为正确。 完成。再次感谢您。

以上是关于从 linux 到 windows 的 C++:'不计算为常数'的主要内容,如果未能解决你的问题,请参考以下文章

将数据序列化代码从 C++ linux/mac 移植到 C++ windows

C++ MinGW 如何从 Windows 编译 Linx

linux到windows C++字节数组

从 VS 窗口 c++ 项目迁移到 linux 项目的最有效方法是啥?

如何把程序从windows平台移植到linux平台

C++:从程序、Windows 和 Linux 中测量内存使用情况 [重复]