1

GCC コンパイラを使用した C/C++ の gnu の世界では、共通関数属性"pure" があります (これは "const" 属性に似ていますが、制限は少ないです)。

多くの関数は戻り値以外には影響を与えず、それらの戻り値はパラメーターやグローバル変数のみに依存します。... 純粋関数の一般的な例として、strlen や memcmp があります。... pure 属性は、 const 属性よりも関数の定義に似ていますがより緩い制限を課します: 関数がグローバル変数を読み取ることを許可します。... 純粋な関数は副作用を持つことができないため、そのような関数が void を返すことは意味がありません。

orのような C++ STL コンストラクターを純粋な関数で呼び出すことは許可されていますstd::stringstd::vector? たとえば、このコードは合法ですか?なぜそうでないのですか? (それは合法__attribute__((const))でしょうか?)

#include <string>
#include <cstdio>
__attribute__((pure)) std::string GetFilesystemSeparator(int unixvar) {
   if(unixvar) {
      return "/";   
   } else {
      return "\\";
   }
}

int main() {
    std::string dirname1="dir1";
    std::string dirname2="dir2";
    std::string filename="file";
    int unixvar;
    std::string path;
    puts("Unix style:");
    unixvar = 1;
    path=dirname1 + GetFilesystemSeparator(unixvar) + dirname2 +  GetFilesystemSeparator(unixvar) + filename;
    puts(path.c_str());


    puts("Not Unix style:");
    unixvar = 0;
    path=dirname1 + GetFilesystemSeparator(unixvar) + dirname2 +  GetFilesystemSeparator(unixvar) + filename;
    puts(path.c_str());
    return 0;
}

g++ pure.cc -o pure -fverbose-asm --save-temps
clang++ pure.cc -o pure1 -O3 -save-temps

複雑な std::sting コンストラクターへの呼び出しがいくつかあります。これは、メモリを割り当て、空きメモリと割り当てられたメモリを管理するために使用されるいくつかのグローバル変数に書き込む場合があります。

less  pure.s
...
_Z22GetFilesystemSeparatorB5cxx11i:
    call    _ZNSaIcEC1Ev@PLT        #
    call    _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEC1EPKcRKS3_@PLT    #

たとえば、"/"and"\\"定数の長さを 100 文字に変更した後、コンストラクターからnewand を呼び出します。malloc(101)

ltrace -e '*@*' ./pure3
...
libstdc++.so.6->strlen("////////////////////////////////"...)                         = 100
libstdc++.so.6->_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE12_M_constructIPKcEEvT_S8_St20forward_iterator_tag(0x7ffc7b66a840, 0x558899f74570, 0x558899f745d4, 0 <unfinished ...>
libstdc++.so.6->_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_createERmm(0x7ffc7b66a840, 0x7ffc7b66a6b0, 0, 0 <unfinished ...>
libstdc++.so.6->_Znwm(101, 0x7ffc7b66a6b0, 0, 0 <unfinished ...>
libstdc++.so.6->malloc(101)                                                           = 0x55889bef0c20
<... _Znwm resumed> )                                                                 = 0x55889bef0c20
<... _ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE9_M_createERmm resumed> )   = 0x55889bef0c20
libstdc++.so.6->memcpy(0x55889bef0c20, "////////////////////////////////"..., 100)    = 0x55889bef0c20
4

1 に答える 1