c++ - 将源代码从 Visual C++ 移植到 GCC 的陷阱是什么

标签 c++ visual-c++ gcc portability

<分区>

众所周知,GCC 比 Visual C++ 更严格地实现 C++ 标准。 坦率地说,Visual C++ 只是没有很好地遵循 C++ 标准。

对于主要使用 Visual C++ 进行开发但需要至少使用 GCC 来移植和编译代码的开发人员来说,这一直是个令人头疼的问题。

一些 Visual C++ 语言不当行为记录在 MSDN Nonstandard Behavior topic 中实际上还有很多其他未记录的案例。

这篇文章的目的是记录 VC++ 与 GCC(最流行的 C++ 编译器)的所有已知兼容性问题。当使用 Visual C++ 编译某些代码片段时没有警告(W4 级别)并且不使用 GCC(产生错误或警告)时会引发问题。

请注意,它仅适用于标准 C++ 问题,Microsoft 特定语言扩展如 __super__forceinline 超出范围。

建议的问题描述格式:

  • 代码片段(使用 Visual C++ 编译成功)
  • 它产生的 GCC 错误或警告
  • 要重现的两个编译器版本
  • 对违反 C++ 标准声明的引用(可选,可以稍后添加)
  • 解决方案(如何修改代码才能被VC++和GCC成功编译)

最佳答案

这是一个相当宽泛的问题,但这里有一些我遇到过的事情:

错误的声明点:

#include <iostream>

struct S {
  S(int) { std::cout << "Incorrect\n"; }
  S(S const &) { std::cout << "Correct\n"; }
};

int s;

int main() {
  S s(s);
}

输出应该是“正确的”,但 Visual Studio(所有版本)的输出是“不正确的”。


复制分配和复制初始化的生成不正确:

#include <iostream>

struct B {
    B &operator = (B &) { std::cout << "Correct\n"; return *this; }
    template<typename T>
    B &operator = (T &) { std::cout << "Incorrect\n"; return *this; }
};

struct D : B {};

int main() {
    D d;
    d = d;
}

我认为这是在 Visual Studio 2012 中修复的。 2012 年之前 VS 的输出是“不正确的”。


两阶段名称查找:

#include <iostream>

static void foo(long) {
  std::cout << "Correct\n";
}

template<typename T>
void bar(T t) {
  foo(t);
}

static void foo(int) {
  std::cout << "Incorrect\n";
}

int main() {
  bar(1);
}

输出应该是“正确的”,但 Visual Studio(目前所有版本)的输出是“不正确的”。


替代 token 不起作用:

int main() <% %>

此程序应该可以编译并运行,但没有任何版本的 Visual Studio 可以成功编译它。


for 循环初始化器子句中的用户定义类型定义:

int main() {
  for (struct {int a;} a = {0}; a.a < 10; ++(a.a)) {

  }
}

这是合法的,但 VS 不允许。


所有这些都可以在 gcc 和 clang 下正确编译和运行,可以追溯到很多版本。 Gcc 曾经在两阶段查找方面存在问题,但现在暂时没有了。

关于c++ - 将源代码从 Visual C++ 移植到 GCC 的陷阱是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25516424/

相关文章:

c++ - 如何使用 Boost.Test 比较文件?

c++ - 类崩溃编译器中的 MSVC 2010 模板化映射

c++ - "BUS_ADRALN - Invalid address alignment"错误是什么意思?

c - 如何找出 malloc() 被分配给哪个变量?

c++ - C4711 "function selected for inline expansion"Visual C++ 警告有什么用?

c - 警告 :initialization from incompatible pointer type

c++ - 字符串流和格式化

c++ - *(void**) 是什么意思

c++ - 在 QLineEdit::textEdited() 内部进行编辑之前获取文本

c++ - 未知(损坏的内存)错误。 sprintf_s 输出.c