文字列s; &S + 1。法的? UB?
-
18-09-2019 - |
質問
次のコードを考えてみます:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myAry[] =
{
"Mary",
"had",
"a",
"Little",
"Lamb"
};
const size_t numStrs = sizeof(myStr)/sizeof(myAry[0]);
vector<string> myVec(&myAry[0], &myAry[numStrs]);
copy( myVec.begin(), myVec.end(), ostream_iterator<string>(cout, " "));
return 0;
}
ここで興味深いのは&myAry[numStrs]
です:numStrsが存在しない何かにとても&myAry[numStrs]
ポイント、5に等しいです。アレイ内の第六の要素。 myVec.end()
、ベクトルmyVec
の一過去端を指す:上記のコードでこれの別の例があります。それは存在しません。この要素のアドレスを取得するためにperfecly法的です。私たちは、string
の大きさを知っているので、string
sのCスタイルの配列の第6要素のアドレスがポイントしなければならないところ、私たちは知っています。限り、我々はそれだけデリファレンス決してこのポインタを評価していないとして、我々はいいですよ。私たちも、平等のために他のポインタと比較することができます。 STLは、イテレータの範囲に作用するアルゴリズムでは、このすべての時間を行います。エンド過去end()
イテレータポイント、ループカウンタ!= end()
ながらループ保つ。
だから今、これを考慮します:
#include <cstdlib>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
string myStr = "Mary";
string* myPtr = &myStr;
vector<string> myVec2(myPtr, &myPtr[1]);
copy( myVec2.begin(), myVec2.end(), ostream_iterator<string>(cout, " "));
return 0;
}
このコードは、法的かつ明確に定義されますか?これは、法的および&myAry[numStrs]
のように、末尾を越えて配列要素のアドレスを取得するために、明確に定義されているので、法的、myPtr
も配列であることをふりをし、明確に定義されなければなりません?
解決
長さ1の配列であったかのようにアレイの「端過去1」、および任意の単一のオブジェクトを処理することができるためのポインタを有することUB合法とはありません。しかし、あなたの代わりに起因するptr + 1
を参照解除してからアドレスを取るの専門的に&ptr[1]
を使用する必要があります。また、これは&array[size]
になってきてarray + size
に適用されます。
あなたが持っていることは動作します。
他のヒント
"加法演算子" 5.6 / 4でC ++標準は述べています:
は、これらの演算子の目的のために、非配列オブジェクトへのポインタは、その要素の型とオブジェクトのタイプと長さ1の配列の最初の要素へのポインタと同様に動作します。
C99の標準6.5.6 / 7は、本質的には同じと言います。