簡體   English   中英

在C ++中,我可以聲明一個引用,以表明什么都不會修改它?

[英]In C++, can I declare a reference so as to indicate that nothing will ever modify it?

如果我做

typedef void Cb();

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

並使用g++ -O3 -save-temps -c foo.cpp ,我看到減法被保留,而如果cb(); 被注釋掉,整個函數優化到

xorl    %eax, %eax

我可以對參數a的規范做些什么,這樣無論對cb()的調用如何都不會優化減法,並且不強制a成為唯一引用(即,它可以在別處引用,但通過這些參考文獻都不會被修改)?

執行建議的優化是不正確的,因為其余代碼可能是:

static int var;

void func()
{
    var++;
}

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

我不知道你可以設置任何特定於編譯器的屬性來說cb()不會修改a

__restrict擴展名,你可以在gcc.godbolt.org上試試這個:

typedef void Cb();

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

奇怪的是, 只有clang進行優化gcc不會這樣做


請注意,類似限制的別名被認為是C ++標准的一部分:

也許將來你可以通過標准來做到這一點。

為什么不移動int x = a; 函數調用下面的行?

如果cb()既不影響x也不影響a ,你應該沒問題,我認為編譯器會再次優化調用,因為x不能在兩次調用之間改變。 如果您無法重新排序這兩個調用,則可能無法首先對其進行優化。

這不是你可以暗示編譯器要做的事情,因為在調用cb()之后無法保證x和a都沒有改變。

將此視為讀/寫訪問的順序 如果在cb()期間沒有對ax讀或寫訪問,則可以手動重新排序函數調用。

如果ax寫的是你不能重新排序和優化將是不正確的。

如果x被讀取,你不能重新排序的函數調用,但如果x確實是只讀的,你可以從一個而不是閱讀,並定義x僅在調用之后,因為它將具有相同的值作為a曾在你面前宣布它呼叫。

如果編譯器支持該擴展,則可以在引用上使用C restrict
(某些編譯器允許__restrict__restrict__ ,它們是implements命名空間的一部分。)

這是您向編譯器的承諾,即對象在任何地方都沒有別名,因此可以對其進行優化。
如果你對編譯器撒了謊,那么你就得到了你應得的破解代碼。

__attribute __((const))就足夠了

如下所述: https//gcc.gnu.org/onlinedocs/gcc-5.1.0/gcc/Function-Attributes.html ,它告訴編譯器給定的函數不修改全局變量(雖然它可以讀取它們)。

還有constpure子集,它也禁止全局讀取。

請考慮以下簡化示例:

int __attribute__((const)) g();

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

g++ 4.8 x86_64 -O3 ,它編譯為:

  • xor %eax,%eax with const
  • 沒有const的大型函數,不假設a不被修改

似乎沒有更細粒度的屬性表示函數不會根據需要修改給定變量。

__attribute __((const))可以應用於函數指針嗎?

我們試試吧:

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

再次,它編譯為xor %eax,%eax ,以及沒有const的大函數,所以答案是肯定的。

這個語法是在: 函數指針__attribute __((const))函數?

它也出現在2011年的郵件列表上: http//comments.gmane.org/gmane.comp.gcc.help/38052至少在當時它只適用於某些屬性。

可以將__attribute __((const))添加到typedef嗎?

這有效:

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

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

要么:

typedef void (g_t)(void);

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

但我無法找到一種方法將屬性放在typedef上傳遞函數,而不是指針,如:

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

GCC發出警告說在這種情況下該屬性被忽略了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM