14

constexpr 変数に一意のアドレスを割り当てることは可能ですか? つまり、変数が使用可能なすべての変換単位で同じ (通常はヘッダーを介して) ことはできますか? 次の例を検討してください。

// foo.hh
#include <iostream>
constexpr int foo = 42;

// a.cc
#include "foo.hh"
void a(void) { std::cout << "a: " << &foo << std::endl; }

// b.cc
#include "foo.hh"
extern void a(void);
int main(int argc, char** argv) {
  a();
  std::cout << "b: " << &foo << std::endl;
}

コンパイルa.ccしてb.cc別々に、gcc 4.7 を使用してそれらをリンクすると、2 つの異なるアドレスが表示されます。ヘッダーにキーワードを追加するとextern、リンカ エラーが発生しますduplicate symbol _foo in: a.o and b.o。これは驚くべきことです。これを追加externすると、コンパイラがそのシンボルを現在のオブジェクトからエクスポートするのではなく、別のオブジェクトからインポートする可能性が高くなると考えたからです。しかし、ここで物事がどのように機能するかについての私の理解は間違っていたようです。

constexpr を 1 つのヘッダーで宣言し、すべての翻訳ユニットが定数式でそれを使用できるようにし、すべての翻訳ユニットがそのシンボルのアドレスに同意するようにする合理的な方法はありますか? このシンボルが実際に属する単一の翻訳単位を示す追加のコードが期待さexternexternますconstexpr

4

3 に答える 3

1

constexpr は、戻り値が定数である関数を意味していると思います。定数変数を constexpr 関数の戻り値にバインドし、代わりにそれを外部に公開できます。例えば:

// constexpr.h
#ifndef __CONSTEXPR_H
#define __CONSTEXPR_H

extern const int foo;

#endif // __CONSTEXPR_H

// constexpr.cpp
#include "constexpr.h"

constexpr int foo_expr()
{
    return 42;
}

const int foo = foo_expr();

// unit1.cpp
#include <iostream>
#include "constexpr.h"

void unit1_print_foo()
{
    std::cout << &foo << " = " << foo << std::endl;
}

// unit2.cpp
#include <iostream>
#include "constexpr.h"

void unit2_print_foo()
{
    std::cout << &foo << " = " << foo << std::endl;
}

// main.cpp
extern void unit1_print_foo();
extern void unit2_print_foo();

int main(int, char**)
{
    unit1_print_foo();
    unit2_print_foo();
}

私の結果は次のとおりです。

$ g++-4.7 -std=c++11 constexpr.cpp unit1.cpp unit2.cpp main.cpp -o test && ./test
0x400ae4 = 42
0x400ae4 = 42

ただし、通常はfoo_expr関数自体を外部から見えるようにするだけで十分であり、呼び出し元はfoo_expr()値を変数のように扱う代わりに値を取得するために使用します。

于 2013-06-05T01:43:44.537 に答える