宽容的旗帜有什么作用?

我只是想知道 -fpermissive标志在 g + + 编译器中是做什么的:

错误: 采用临时[-fpermissive ]地址

我可以通过给编译器 -fpermissive标志来解决这个问题。

编辑: 我刚刚找到了导致临时地址错误的原因! 我现在要修复这个部分。

230860 次浏览

-fpermissive旗帜使编译器报告一些实际上是错误的东西(但是有些编译器允许这样做)作为警告,以允许代码编译,即使它不符合语言规则。你真的应该解决根本的问题。发布演示问题的最小的可编译代码示例。

-fpermissive
将一些关于不一致代码的诊断从错误降级为警告。 因此,使用 -fpermissive将允许编译一些不一致的代码。

来自 那些文件:

-fpermissive
将一些关于不一致代码的诊断从错误降级为警告。 因此,使用 -fpermissive将允许编译一些不一致的代码。

底线: 别用它,除非你知道你在做什么!

当你写了一些语言标准不允许的东西(因此不能真正定义好行为,这是不这样做的充分理由) ,但碰巧映射到 一些类型的可执行文件,如果天真地提供给编译引擎,那么 -fpermissive就会这样做,而不是停止这个错误消息。在某些情况下,程序的行为将完全符合您最初的设想,但是您绝对不应该依赖它,除非您有一些非常特殊的理由不使用其他解决方案。

如果您想要一个真实的用例,那么可以尝试编译一个非常老的 X Windows 版本——比如,从2004年左右开始的 XFree86或 XOrg,就在拆分前后——使用“现代”(咳嗽)版本的 gcc,比如4.9.3。

您会注意到构建 CFLAGS 同时指定了“-ansi”和“-pedantic”。从理论上讲,这意味着“如果有任何东西稍微违反了语言规范,就会爆炸”。实际上,3.x 系列的 gcc 并没有捕捉到很多这样的东西,并且用4.9.3构建它将在地面上留下一个冒烟的洞,除非你将 CFLAGS 和 BootSTRAPFLAGS 设置为“-fpermissive”。

使用这个标志,这些 C 文件中的大多数将实际构建,让您可以自由地转移到 lexer 将生成的依赖于版本的残骸。=]

简单地设置-fpermissive 并且不使用它存在的一个常见情况是: 经过彻底测试和工作的第三方库,如果没有-fpermissive,就不能在较新的编译器版本上编译。这些库的存在,很可能不是应用程序开发人员要解决的问题,也不在开发人员的计划预算中。

在这种情况下,放任自流,继续前进。

一般的答案是,它“将一些关于不一致代码的诊断从错误降级为警告。”

不幸的是,我还没有看到它允许的具体清单。

我发布答案的主要原因是建议你尽可能避免使用它。相反,查看每个错误,看看是否可以修复。OP 发现并修复了导致他们错误的原因。(“获取临时对象的地址”可以类似于调用返回 std: : string 对象的函数,并为临时对象的 c _ ptr ()值赋值。)

我刚刚回顾了一个涉及到升级 gcc 版本的项目,开发人员添加了 -fpermissive,因为突然出现了一堆编译错误。我注意到一个测试是:

    if (myPointer == '\0')

我指出,它真的应该是:

    if (myPointer[0] == '\0')

开发人员检查后发现,每一个标记的东西都是一个真正的错误——其中一些已经存在了超过20年。

就像@cli _ hlt 提到的

底线: 不要使用它,除非你知道你在做什么!

它会做一些可怕的事情,比如编译器有时会取消 std::map变量的常量:

#include <map>
#include <vector>
#include <iostream>
#include <string>
struct B{
std::map<std::string, int> m_map;
std::vector<int> m_vector;
B(){
m_map["a"] = 1;
m_map["b"] = 2;
m_map["c"] = 3;
m_vector.emplace_back(1);
m_vector.emplace_back(2);
m_vector.emplace_back(3);
}
const std::map<std::string, int>& getMap() const {
return m_map;
}
const int& getMapValue(const std::string& key) const {
return m_map.at(key);
}
const std::vector<int>& getVector() const {
return m_vector;
}
const int& getVectorValue(const int& i) const {
return m_vector[i];
}
};


int main(){
B b;
auto& my_map = b.getMap(); // we get const ref here
my_map["a"] = 10; // here we can modify it
std::cout << "my_map[a]=" << my_map.at("a") << std::endl;


auto& my_map2 = b.getMap();  // here we return already modified variable
std::cout << "my_map2[a]=" << my_map2.at("a") << std::endl;


auto& my_value = b.getMapValue("b");
// my_value = 20; // compiler error
// std::cout << "my_map[b]=" << my_value << std::endl;


auto& my_vector = b.getVector();
// my_vector[0] = 10; // compiler error
// std::cout << "my_vector[0]=" << my_vector[0] << std::endl;


const int a = 10;
auto& a1 = a;
// a1 = 100; // compiler error
}

正如您所看到的,您不能保证映射的常量,但是,向量或值的常量可以被保留。 另外,我在下面的编译器中测试了 GCC 12.1,9.1,8.1,7.1,6.1。 但是,clang 不允许标记 拿着这个,它会捕获错误。