벡터 캐스트에서 정의되지 않은 동작


19

이 코드가 정의되지 않은 숫자의 초기화되지 않은 정수를 쓰는 이유는 무엇입니까?

#include <iostream>
#include <vector>
using namespace std;


int main()
{
    for (int i : vector<vector<int>>{{77, 777, 7777}}[0])
        cout << i << ' ';
}

나는 출력이 될 것으로 예상했다 77 777 7777.

이 코드는 정의되어 있지 않습니까?

답변:


18

vector<vector<int>>{{77, 777, 7777}}는 일시적이며 vector<vector<int>>{{77, 777, 7777}}[0]원거리에서 사용 하는 것은 정의되지 않은 행동입니다.

먼저 변수를 만들어야합니다

#include <iostream>
#include <vector>
using namespace std;


int main()
{
    auto v = vector<vector<int>>{{77, 777, 7777}};
    for(int i: v[0])
        cout << i << ' ';
}

또한 Clang 10.0.0을 사용하면이 동작에 대한 경고가 표시됩니다.

경고 : 전체 표현식 [-Wdangling-gsl] 벡터> {{77, 777, 7777}} [0]의 끝에서 포인터를지지하는 객체가 파괴됩니다.


2
이 나쁜 습관이 퍼지는 것을 막기 위해 using std::vector대신에 사용하십시오 using namespace std;.
infinitezero

10

반복하는 벡터가 루프에 들어가기 전에 파괴되기 때문입니다.

이것은 일반적으로 일어나는 일입니다.

auto&& range = vector<vector<int>>{{77, 777, 7777}}[0];
auto&& first = std::begin(range);
auto&& last = std::end(range);
for(; first != last; ++first)
{
    int i = *first;
    // the rest of the loop
}

문제는 다음과 같이 평가되므로 첫 번째 줄에서 시작됩니다.

  1. 먼저 주어진 인수로 벡터의 벡터를 구성하면 해당 벡터는 이름이 없으므로 임시가됩니다.

  2. 그런 다음 범위 참조는 아래 첨자 벡터에 바인딩되며 벡터가 포함 된 벡터가 유효한 경우에만 유효합니다.

  3. 세미콜론에 도달하면 임시 벡터가 파괴되고 소멸자에서 아래 첨자 벡터를 포함하는 저장된 벡터를 파괴하고 할당 해제합니다.

  4. 결국 반복 된 벡터에 대한 참조로 끝납니다.

이 문제를 피하려면 두 가지 해결책이 있습니다.

  1. 루프가 포함 된 범위가 끝날 때까지 지속되도록 루프 전에 벡터를 선언하십시오.

  2. C ++ 20에는 이러한 문제를 해결하기 위해 제공되는 init 문이 포함되어 있으며 루프 후 벡터를 즉시 파괴하려는 경우 첫 번째 방법보다 낫습니다.

    for (vector<vector<int>> vec{{77, 777, 7777}}; int i : vec[0])
    {
    }

이것은 "일반적으로"일어나지 않습니다. 이 정확한 동작 (및 적절한 범위 지정 및 이름 지정에 대한 고려 사항)은 표준에 따라 규정되며 as-if 규칙이 적용됩니다.
Konrad Rudolph

나는 일생을 말하고있다. 당신이 손으로 같은 코드를 작성하더라도 당신은 당신이 원하는 동작을 얻을 수 있다는 보장이 컴파일러는 그것이 무엇 최적화를 할 수 할 것입니다
dev65

TIL C ++ 20 선언 범위-범위 구문. 행복하거나 슬플 지 잘 모르겠습니다.
날개를 가진 소행성

6
vector<vector<int>>{{77, 777, 7777}}[0]

나는 이것이 매달려 있다고 기대한다.

원거리에 대한 정의는 콜론의 RHS가 지속 기간 동안 "사용 중"으로 남아 있음을 보장하지만 여전히 임시를 첨자하고 있습니다. 아래 첨자의 결과 만 유지되지만 그 결과는 참조이며 실제 벡터는 선언 된 전체 표현식 을 지나도 살아남을 수 없습니다 . 그것은 전체 루프를 설명하지 않습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.