忽略"taking address of temporary"错误

Ignore "taking address of temporary" error

本文关键字:temporary 错误 of address taking 忽略      更新时间:2023-10-16

对于此代码

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

gcc-4.6会发出两个"taking address of temporary[-fpermission]"错误。这是在4.6中引入的,gcc-4.5可以编译它

原因非常清楚,并且有充分的记录。问题是,它是一个遗留代码,要进行编译,我们必须使其工作,因此,在文件和/或代码部分周围执行#pragmas,以使用-fpermission进行编译。比方说,客户坚决不修改现有的代码(即用&f()或&test()不能更改,通常不能更改源文件)。换句话说,以某种方式编译这个,唯一的选择是或多或少的痛苦。

因此,问题是——有没有可能的变通办法让它在很多地方都能在不做的情况下发挥作用-W标志、C++技巧等。

我的意思是,用&f()或&test()无法更改。

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

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

您可以通过创建一个额外的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() );

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

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

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

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

我不清楚你对什么有多大的控制权,但下面的破解似乎有效:

编辑:最初让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());
}

破解方法基本上是将临时变量转换为常量引用,这样编译器会更高兴。它不应该被普遍使用,它的唯一目的是关闭编译器。但是,它并没有真正解决客户代码或提供的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