在C ++中,我可以声明一个引用,以表明没有任何东西可以修改它吗?

时间:2022-04-12 05:33:43

If I do

如果我做

typedef void Cb();

int foo(int const& a, Cb cb) {
  int x = a;
  cb();
  return x - a;
}

and compile with g++ -O3 -save-temps -c foo.cpp, I see that the subtraction is preserved, whereas if cb(); is commented out, the entire function optimizes to

并使用g ++ -O3 -save-temps -c foo.cpp进行编译,我看到减法被保留,而如果cb();被注释掉,整个函数优化到

xorl    %eax, %eax

Is there something I can do to the specification of the parameter a so that the subtraction will be optimized out regardless of the call to cb(), and without forcing a to be a unique reference (ie, that it may be referred to elsewhere, but that via none of those references will it be modified)?

我可以对参数a的规范做些什么,这样无论对cb()的调用如何都不会优化减法,并且不强制a成为唯一引用(即,它可以在别处引用,但是那些引用都不会被修改)?

5 个解决方案

#1


15  

There's the __restrict extension, you can try this on gcc.godbolt.org:

有__restrict扩展名,你可以在gcc.godbolt.org上试试这个:

typedef void Cb();

int foo(const int & __restrict a, Cb cb) {
  int x = a;
  cb();
  return x - a;
}

Curiously, only clang does the optimization, gcc doesn't do it.

奇怪的是,只有clang进行优化,gcc不会这样做。


Notice that restrict-like aliasing is being considered to be part of the C++ standard:

请注意,类似限制的别名被认为是C ++标准的一部分:

Maybe in the future you can do it by the standard.

也许在将来你可以通过标准来做到这一点。

#2


15  

Doing the suggested optimization would be incorrect because the rest of the code might be:

执行建议的优化是不正确的,因为其余代码可能是:

static int var;

void func()
{
    var++;
}

// ...
foo(var, func);

I'm not aware of any compiler-specific attribute you can set to say that cb() will not modify a.

我不知道你可以设置任何特定于编译器的属性来说cb()不会修改a。

#3


6  

Why don't you just move the int x = a; line below the function call?

你为什么不移动int x = a;函数调用下面的行?

If cb() influences neither x nor a, you should be fine doing that, and I think the compiler will optimize the call again, because x cannot change between the two calls. If there is a reason why you cannot reorder these two calls, you can probably not optimize it in the first place.

如果cb()既不影响x也不影响a,你应该没问题,我认为编译器会再次优化调用,因为x不能在两次调用之间改变。如果您无法重新排序这两个调用,则可能无法首先对其进行优化。

This is not something you can hint the compiler to do though, since there is no way to guarantee that neither x nor a have changed after the call to cb().

这不是你可以暗示编译器要做的事情,因为在调用cb()之后无法保证x和a都没有改变。

Think about this as an order of read/write accesses. If no read or write access to a and x happens during cb(), you can do a manual reordering of the function-call.

将此视为读/写访问的顺序。如果在cb()期间没有对a和x进行读或写访问,则可以对函数调用进行手动重新排序。

If a or x is written, you cannot reorder, and the optimization would not be correct.

如果写入或x,则无法重新排序,并且优化不正确。

If x is read, you cannot reorder the function call, but if x truly is only read, you could read from a instead, and define x only after the call since it will have the same value as a, had you declared it before the call.

如果读取了x,则无法对函数调用进行重新排序,但如果只读取x,则可以从a读取,并且仅在调用后定义x,因为它具有与a相同的值,如果你在之前声明了它呼叫。

#4


5  

You could use the C restrict on the reference, if your compiler supports that extension.
(Some compiler allow __restrict or __restrict__, which are part of the implementations namespace.)

如果编译器支持该扩展,则可以对引用使用C restrict。 (某些编译器允许__restrict或__restrict__,它们是implements命名空间的一部分。)

That's a promise from you to the compiler that the object is not aliased anywhere, and it can thus optimize it.
If you lied to the compiler, well, you get the broken code you deserve.

这是您向编译器承诺的对象在任何地方都没有别名,因此可以对其进行优化。如果你对编译器说谎,那么你就得到了你应得的破解代码。

#5


-1  

__attribute__((const)) is enough

__attribute __((const))就足够了

As documented at: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html , it tells the compiler that the given function does not modify globals (although it can read them).

如下所述:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html,它告诉编译器给定的函数不修改全局变量(虽然它可以读取它们)。

There is also the pure subset of const, which also forbids global reads.

还有const的纯子集,它也禁止全局读取。

Consider the following simplified example:

请考虑以下简化示例:

int __attribute__((const)) g();

int f(int a) {
  int x = a;
  g();
  return x - a;
}

On g++ 4.8 x86_64 -O3, it compiles to:

在g ++ 4.8 x86_64 -O3上,它编译为:

  • xor %eax,%eax with const
  • xor%eax,%eax with const

  • a large function that does not suppose a is not modified without const
  • 没有const的大型函数,不会假设a不被修改

There seems to be no finer grained attribute that says that a function does not modify a given variable as you require.

似乎没有更细粒度的属性表示函数不会根据需要修改给定变量。

Can __attribute__((const)) be applied to function pointers?

可以将__attribute __((const))应用于函数指针吗?

Let's try:

int f(int& a, void __attribute__((const)) (*g)(void)) {
    int x = a;
    (*g)();
    return x - a;
}

Once again, it compiles to xor %eax,%eax, and to a large function without const, so the answer is yes.

再一次,它编译为xor%eax,%eax,以及没有const的大函数,所以答案是肯定的。

This syntax was asked at: Function pointer to __attribute__((const)) function?

这个语法是在:函数指针__attribute __((const))函数?

It also appeared in 2011 on the mailing list at: http://comments.gmane.org/gmane.comp.gcc.help/38052 At the time at least, it only worked for some attributes.

它也出现在2011年的邮件列表上:http://comments.gmane.org/gmane.comp.gcc.help/38052至少在当时它只适用于某些属性。

Can __attribute__((const)) be added to the typedef?

可以将__attribute __((const))添加到typedef中吗?

This works:

typedef void __attribute__((const)) (*g_t)(void);

int f(int& a, g_t g) {
    int x = a;
    (*g)();
    return x - a;
}

or:

typedef void (g_t)(void);

int f(int& a, g_t __attribute__((const)) g) {
    int x = a;
    g();
    return x - a;
}

But I couldn't find a way to both put the attribute on the typedef and pass a function, not a pointer, like:

但我无法找到一种方法将属性放在typedef上并传递函数,而不是指针,如:

typedef void __attribute__((const)) (g_t)(void);

GCC gives a warning saying the attribute was ignored in this case.

GCC发出警告说在这种情况下该属性被忽略了。

#1


15  

There's the __restrict extension, you can try this on gcc.godbolt.org:

有__restrict扩展名,你可以在gcc.godbolt.org上试试这个:

typedef void Cb();

int foo(const int & __restrict a, Cb cb) {
  int x = a;
  cb();
  return x - a;
}

Curiously, only clang does the optimization, gcc doesn't do it.

奇怪的是,只有clang进行优化,gcc不会这样做。


Notice that restrict-like aliasing is being considered to be part of the C++ standard:

请注意,类似限制的别名被认为是C ++标准的一部分:

Maybe in the future you can do it by the standard.

也许在将来你可以通过标准来做到这一点。

#2


15  

Doing the suggested optimization would be incorrect because the rest of the code might be:

执行建议的优化是不正确的,因为其余代码可能是:

static int var;

void func()
{
    var++;
}

// ...
foo(var, func);

I'm not aware of any compiler-specific attribute you can set to say that cb() will not modify a.

我不知道你可以设置任何特定于编译器的属性来说cb()不会修改a。

#3


6  

Why don't you just move the int x = a; line below the function call?

你为什么不移动int x = a;函数调用下面的行?

If cb() influences neither x nor a, you should be fine doing that, and I think the compiler will optimize the call again, because x cannot change between the two calls. If there is a reason why you cannot reorder these two calls, you can probably not optimize it in the first place.

如果cb()既不影响x也不影响a,你应该没问题,我认为编译器会再次优化调用,因为x不能在两次调用之间改变。如果您无法重新排序这两个调用,则可能无法首先对其进行优化。

This is not something you can hint the compiler to do though, since there is no way to guarantee that neither x nor a have changed after the call to cb().

这不是你可以暗示编译器要做的事情,因为在调用cb()之后无法保证x和a都没有改变。

Think about this as an order of read/write accesses. If no read or write access to a and x happens during cb(), you can do a manual reordering of the function-call.

将此视为读/写访问的顺序。如果在cb()期间没有对a和x进行读或写访问,则可以对函数调用进行手动重新排序。

If a or x is written, you cannot reorder, and the optimization would not be correct.

如果写入或x,则无法重新排序,并且优化不正确。

If x is read, you cannot reorder the function call, but if x truly is only read, you could read from a instead, and define x only after the call since it will have the same value as a, had you declared it before the call.

如果读取了x,则无法对函数调用进行重新排序,但如果只读取x,则可以从a读取,并且仅在调用后定义x,因为它具有与a相同的值,如果你在之前声明了它呼叫。

#4


5  

You could use the C restrict on the reference, if your compiler supports that extension.
(Some compiler allow __restrict or __restrict__, which are part of the implementations namespace.)

如果编译器支持该扩展,则可以对引用使用C restrict。 (某些编译器允许__restrict或__restrict__,它们是implements命名空间的一部分。)

That's a promise from you to the compiler that the object is not aliased anywhere, and it can thus optimize it.
If you lied to the compiler, well, you get the broken code you deserve.

这是您向编译器承诺的对象在任何地方都没有别名,因此可以对其进行优化。如果你对编译器说谎,那么你就得到了你应得的破解代码。

#5


-1  

__attribute__((const)) is enough

__attribute __((const))就足够了

As documented at: https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html , it tells the compiler that the given function does not modify globals (although it can read them).

如下所述:https://gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html,它告诉编译器给定的函数不修改全局变量(虽然它可以读取它们)。

There is also the pure subset of const, which also forbids global reads.

还有const的纯子集,它也禁止全局读取。

Consider the following simplified example:

请考虑以下简化示例:

int __attribute__((const)) g();

int f(int a) {
  int x = a;
  g();
  return x - a;
}

On g++ 4.8 x86_64 -O3, it compiles to:

在g ++ 4.8 x86_64 -O3上,它编译为:

  • xor %eax,%eax with const
  • xor%eax,%eax with const

  • a large function that does not suppose a is not modified without const
  • 没有const的大型函数,不会假设a不被修改

There seems to be no finer grained attribute that says that a function does not modify a given variable as you require.

似乎没有更细粒度的属性表示函数不会根据需要修改给定变量。

Can __attribute__((const)) be applied to function pointers?

可以将__attribute __((const))应用于函数指针吗?

Let's try:

int f(int& a, void __attribute__((const)) (*g)(void)) {
    int x = a;
    (*g)();
    return x - a;
}

Once again, it compiles to xor %eax,%eax, and to a large function without const, so the answer is yes.

再一次,它编译为xor%eax,%eax,以及没有const的大函数,所以答案是肯定的。

This syntax was asked at: Function pointer to __attribute__((const)) function?

这个语法是在:函数指针__attribute __((const))函数?

It also appeared in 2011 on the mailing list at: http://comments.gmane.org/gmane.comp.gcc.help/38052 At the time at least, it only worked for some attributes.

它也出现在2011年的邮件列表上:http://comments.gmane.org/gmane.comp.gcc.help/38052至少在当时它只适用于某些属性。

Can __attribute__((const)) be added to the typedef?

可以将__attribute __((const))添加到typedef中吗?

This works:

typedef void __attribute__((const)) (*g_t)(void);

int f(int& a, g_t g) {
    int x = a;
    (*g)();
    return x - a;
}

or:

typedef void (g_t)(void);

int f(int& a, g_t __attribute__((const)) g) {
    int x = a;
    g();
    return x - a;
}

But I couldn't find a way to both put the attribute on the typedef and pass a function, not a pointer, like:

但我无法找到一种方法将属性放在typedef上并传递函数,而不是指针,如:

typedef void __attribute__((const)) (g_t)(void);

GCC gives a warning saying the attribute was ignored in this case.

GCC发出警告说在这种情况下该属性被忽略了。