3

これは、この質問に似ています (ただし、異なります) 。

以下は、私が Sun CC で発見した奇妙な点を説明するための簡単なテスト コードです。

//---------------main.cpp
#include "wtc.hpp"

int main(int, char**)
{
  testy t;
  t.lame(99);
  return 0;
}
//--------------wtc.hpp
#ifndef WTC_HPP_INCLUDED
#define WTC_HPP_INCLUDED

class testy
{
public:
  void lame(int );
};

#endif 

//---------------wtc.cpp
#include <iostream>
#include "wtc.hpp"

void testy::lame(const int a)
{
  std::cout << "I was passed " << a << "\n";
}

//---------------makefile
#CXX=CC
CXX =g++
#CXXFLAGS= -g 
CXXFLAGS= -g3 -Wall -Werror

OBJECTS=$(patsubst %.cpp,%.o,$(wildcard *.cpp))

all : $(OBJECTS)
    $(CXX) $(CXXFLAGS) -o $@ $^

.PHONY: clean
clean :
    rm *.o

これが g++ を使用してコンパイルされた場合、コンパイル、リンク、および実行時に期待されることを行います。++a; を追加することもできます。testy::lame() では、コンパイラは読み取り専用変数の変更について不平を言うでしょう (そうあるべきです)。

ただし、CC を使用してコンパイルすると、次のリンカ エラーが発生します。

CC -g   -c -o main.o main.cpp
CC -g   -c -o wtc.o wtc.cpp
CC -g -o all main.o wtc.o
Undefined                       first referenced
 symbol                             in file
void testy::lame(int)               main.o
ld: fatal: Symbol referencing errors. No output written to all
make: *** [all] Error 1

nm と C++filt でオブジェクト コードをチェックすると、g++ バージョンでは testy::lame(int) シンボルが作成されるのに対し、CC では testy::lame(const int) が作成されるため、リンカー エラーが発生することがわかりました。

私は Stroustrup の本でそれを調べましたが、このテクニックが言及されているのを見つけることができません (それが存在しないという意味ではありません!)。これは本当にコンパイラのバグなのか、それとも Solaris 以外のどこでも機能する単なるハックなのか?

4

7 に答える 7

25

これは のコンパイラの問題のようCCです。C++ 標準は次のように述べています (13.1 Overloadable 宣言で)​​:

const や volatile の有無のみが異なるパラメーター宣言は同等です。つまり、各パラメーター型の const および volatile 型指定子は、どの関数が宣言、定義、または呼び出されているかを判断するときに無視されます。

しかし、標準がその後すぐに言及しているように、オーバーロードに参加できるconst/修飾子があります。volatile

この方法で無視されるのは、パラメーター型指定の最も外側のレベルにある const および volatile 型指定子のみです。パラメーターの型指定内に埋め込まれた const および volatile 型指定子は重要であり、オーバーロードされた関数宣言を区別するために使用できます。

于 2009-04-20T14:48:08.600 に答える
4

「const int」パラメーターの「const」は、コンパイラーによって無視されます。ただし、宣言と定義の違いは、控えめに言っても、悪いスタイルです。

于 2009-04-20T14:47:43.953 に答える
1

私の理解では、呼び出し元にとってほとんど違いがないため、これは許可されています。const は関数ではなく、パラメーターであり、定義に追加しています。したがって、実際に追加した const は実装のみに影響します

この質問を参照してください。

于 2009-04-20T14:48:26.463 に答える
0

constintは値によって渡されるため、 isvoid func1(const int)は関数に何の影響も与えません。つまり、intのコピーが作成され、そのコピーは関数呼び出しの間だけ存続します。そのコピーを変更するかどうかは、何の関係もありません。

void func2(const char*)あなたはおそらく、が重要であるという事実に混乱していconstます。しかし、それはとは異なることを認識しなければなりませんvoid func3(char* const)。前者では、変更できないのは指摘されたキャラクターです。後者の場合、(無関係に)'const'であるのはポインタです。

于 2009-04-20T15:21:39.660 に答える
0

私は常にconst宣言と定義の両方に一致します。これにより、署名が一致するため、問題が軽減されます。

于 2009-04-20T14:43:39.080 に答える
0

Alexandrescu #15 による C++ コーディング標準を参照してください。これは彼によればうまくいくはずです。const は、関数の実装者が入力変数を変更するのを防ぎます。IMO変数は、関数内でconstのままにする必要があります。変数が必要な場合は、変数を宣言します。オプティマイザーはそれを取り除きます。

int temp = a;

これはここでは機能しないため、プロトタイプと実装の両方で (const int a) を使用するようクラスにアドバイスしています。私は、すべてのコンパイラで機能する手法を使用することの大ファンです。

于 2012-09-22T00:19:01.370 に答える
-2

はい、const int は int と同じではありません。

于 2009-04-20T14:45:16.877 に答える