0

对于此代码

struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
    print(&f());
    print(&test());
}

gcc-4.6 发出两个“获取临时 [-fpermissive] 的地址”错误。这是在 4.6 中引入的,gcc-4.5 可以编译它。

原因很清楚并且有据可查。问题是它是遗留代码,要编译,我们必须让它工作,因此,围绕文件和/或部分代码执行#pragmas 以使用-fpermissive 编译它们。假设客户坚持不修改现有代码(即不能更改使用 &f() 或 &test() 调用 print() 的事实,而不是一般的源文件)。换句话说,这种或另一种方式被编译,唯一的选择是或多或少的痛苦。

所以问题是 - 是否有任何可能的解决方法可以使其在很多地方不使用 -fpermissive 的情况下工作?-W 标志、C++ 技巧等。

4

4 回答 4

4

我的意思是,不能改变用 &f() 或 &test() 调用 print() 的事实。

如果您可以控制类型本身,则始终可以重载引用运算符operator&, 并this从中返回。在一般情况下这不是一件好事,但考虑到您正在返回正确类型的正确指针,它是相当安全的。

如果涉及基类,那么它变得相当复杂。您需要使用虚拟运算符重载,并且层次结构中的每个类都需要单独实现它。

于 2012-07-23T18:53:42.260 回答
2

为什么不直接重写代码以完全按照编译器所做的工作而不会抱怨呢?换句话说,将您的临时变量存储在临时(但可寻址)变量中。

struct test {};
test f() { return test(); }
void print(test *x) {}
int main()
{
    test t1 = f();
    test t2 = test();
    print(&t1);
    print(&t2);
}

这应该与旧编译器版本的行为方式相同。告诉客户新的编译器要求您更改代码以明确编译器过去隐式执行的操作。

于 2013-03-06T22:46:28.770 回答
2

您可以通过创建一个额外的重载来提供解决方法,该print重载将采用const&

void print( test const & t ) {
   print(&t);             // Assuming that the function is 'print( test const * )'
                          // a print function should not take a non-const pointer!
}

并将调用者更改为:

print( f() );

这需要更改代码,但形式非常有限,因此可能是可以接受的。另请注意

于 2012-07-23T18:23:31.477 回答
0

我不清楚你对什么有多少控制权,但以下黑客似乎有效:

编辑:最初f返回的是引用而不是副本。DeadMG 正确地指出,一旦使用临时文件,这会导致未定义的行为,因此恢复f为返回副本。

struct test {};
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
test f() { return test(); }
#define f() test_copy(f())
void print(const test *) {}
int main()
{
    print(&f());
    print(&test());
}

hack 基本上是将您的临时变量转换为 const 引用,以便编译器更快乐。它不应该普遍可用,它的唯一目的是关闭编译器。但是,它并没有真正解决客户代码或提供的 API 的任何潜在问题。您可以修复您的 API,并且只对某些客户使用黑客攻击:

struct test {};
test f() { return test(); }
void print(const test &) {}

#define CUSTOMER_NEEDS_HACK
#ifdef CUSTOMER_NEEDS_HACK
const test & test_copy (const test &t) { return t; }
#define test() test_copy(test())
#define f() test_copy(f())
void print(const test *t) { print(*t); }
#endif
于 2012-07-23T19:30:12.150 回答