code

C 스타일 언어에서 익명 {}개 블록의 목적은 무엇입니까?

starcafe 2023. 6. 12. 21:38
반응형

C 스타일 언어에서 익명 {}개 블록의 목적은 무엇입니까?

C 스타일 언어(C, C++, C#)에서 익명 {}개 블록의 용도는 무엇입니까?

예 -



void function()
{

  {
    int i = 0;
    i = i + 1;
  }

  {
    int k = 0;
    k = k + 1;
  }

}

편집 - 훌륭한 답변을 주셔서 감사합니다!

변수의 범위를 {} 내부의 블록으로 제한합니다.

대괄호는 범위 영역을 지정합니다. 대괄호 내에서 선언된 모든 항목은 대괄호 밖에서 보이지 않습니다.

또한 C++에서 스택에 할당된 객체(예: 'new'를 사용하지 않음)는 범위를 벗어나면 파괴됩니다.

경우에 따라 작성자가 소스를 보는 사람들에게 주의를 기울일 가치가 있다고 느끼는 기능의 특정 부분을 강조하는 방법이 될 수도 있습니다.이것이 좋은 용도인지 아닌지는 논쟁의 여지가 있지만, 저는 그것을 해내는 것을 보았습니다.

개체가 범위를 벗어날 때 지정된 리소스가 해제됨을 의미하는 RAII 용도로 유용한 경우가 많습니다.예:

void function()
{
    {
        std::ofstream out( "file.txt" );
        out << "some data\n";
    }
    // You can be sure that "out" is closed here
}

새 범위를 만들면 스위치 문에서 로컬 변수를 정의하는 데 사용할 수 있습니다.

예.

switch (i)
{
    case 0 :
        int j = 0;   // error!
        break;

대.

switch (i)
{
    case 0 :
    {
        int j = 0;   // ok!
    }
    break;

{ ... }.

C++에서는 다음과 같이 사용할 수 있습니다.

void function() {
    // ...
    {
        // lock some mutex.
        mutex_locker lock(m_mutex);
        // ...
    }
    // ...
}

블록 밖으로 컨트롤이 나가면 뮤텍스 락커가 파괴됩니다.그리고 그것의 소멸기에서, 그것은 자동으로 그것이 연결된 뮤텍스의 잠금을 해제합니다.이 작업은 매우 자주 수행되며 RAII(리소스 수집은 초기화) 및 SBRM(범위에 제한된 리소스 관리)이라고도 합니다.또 다른 일반적인 응용 프로그램은 메모리를 할당한 다음 소멸기에서 해당 메모리를 다시 해제하는 것입니다.

또 다른 목적은 몇 가지 유사한 작업을 수행하는 것입니다.

void function() {
    // set up timer A
    {
        int config = get_config(TIMER_A);
        // ... 
    } 

    // set up timer B
    {
        int config = get_config(TIMER_B);
        // ...
    } 
}

그것은 사람들이 다른 빌딩 블록들을 쉽게 찾을 수 있도록 물건들을 분리해 둘 것입니다.변수는 범위 밖에서 볼 수 없으므로 서로 충돌하지 않으므로 위의 코드와 같이 이름이 같은 변수를 사용할 수 있습니다.

다른 의 "OpenGL"입니다.glPushMatrix()그리고.glPopMatrix()행렬 스택과 관련된 논리 블록을 생성하는 함수:

glPushMatrix();
{
    glTranslate(...);
    glPushMatrix();
    {
        glRotate(...);
        // draw some stuff
    }
    glPopMatrix();
    // maybe draw some more stuff
}
glPopMatrix();
class ExpensiveObject {
public:
    ExpensiveObject() {
        // acquire a resource
    }
    ~ExpensiveObject() {
        // release the resource
    }
}

int main() {
    // some initial processing
    {
        ExpensiveObject obj;
        // do some expensive stuff with the obj
    } // don't worry, the variable's scope ended, so the destructor was called, and the resources were released
    // some final processing
}

범위 지정은 물론입니다.(저 말은 아직 두들겨 맞아 죽었습니까?)

그러나 언어 정의를 살펴보면 다음과 같은 패턴을 볼 수 있습니다.

  • 한다면 ( 표현 )   진술
  • 한다면 ( 표현 )   진술   또 다른   진술
  • 스위치 ( 표현 )   진술
  • 하는 동안에 ( 표현 )   진술
  • 하다, 하다, 하다, 하다, 하다, 하다, 하다, 하다, 나다   진술   하는 동안에 ( 표현 ) ;

그것은 복합 진술이 가능한 여러 진술 중 하나일 뿐이라는 언어 구문을 단순화합니다.


복합 문: {문-목록opt}

목록:

  • 진술
  • 명세서 목록   진술

:

  • 꼬리표가 붙은 진술
  • 표현식의
  • 복합 진술
  • 선발명세서
  • 반복 진술
  • 과장된 진술
  • 선언문
  • 트라이블록

당신은 두 가지 일을 하고 있습니다.

  1. 해당 블럭의 변수에 범위 제한을 적용하고 있습니다.
  2. 형제 코드 블록에서 동일한 변수 이름을 사용할 수 있습니다.

변수의 범위를 지정하는 데 사용되는 경우가 많기 때문에 변수는 대괄호로 정의된 임의 블록에 대해 로컬입니다.예를 들어, 변수 i 및 k는 괄호 밖에서 액세스할 수 없으므로 몰래 수정할 수 없으며 변수 이름은 코드의 다른 곳에서 다시 사용할 수 있습니다.가비지 수집이 있는 언어에서는 가비지 수집기가 범위 밖의 변수를 정리해도 안전하다는 것을 알고 있기 때문에 가비지 수집기를 사용하여 이와 같은 로컬 범위를 만들 수 있습니다.C/C++에서는 사용할 수 없지만, C#에서는 사용할 수 있어야 한다고 생각합니다.

생각해 볼 수 있는 한 가지 간단한 방법은 브레이스가 네임스페이스, 함수 또는 메소드와 같은 원자 코드 조각을 정의하지만 실제로 네임스페이스, 함수 또는 메소드를 만들 필요는 없습니다.

제가 이해하기로는, 그것들은 단순히 범위를 좁히기 위한 것입니다.이러한 변수를 사용하면 상위/자매 범위에서 변수 이름을 재사용할 수 있으며, 이는 때때로 유용할 수 있습니다.

편집: 이 질문은 실제로 다른 스택 오버플로 질문에 답했습니다.도움이 되길 바랍니다.

앞의 포스터에서 언급했듯이 변수의 사용을 선언된 범위로 제한합니다.

C# 및 Java와 같은 가비지 수집 언어에서는 가비지 수집기가 범위 내에서 사용되는 모든 변수에 의해 사용되는 메모리를 회수할 수 있습니다(변수를 null로 설정하면 동일한 영향을 받음).

{
    int[] myArray = new int[1000];
    ... // Do some work
}
// The garbage collector can now reclaim the memory used by myArray

이는 범위와 관련된 것으로, 프로그램의 한 부분에 있는 변수와 메서드를 해당 프로그램의 다른 부분에 표시하는 것을 의미합니다. 다음 예를 고려해 보십시오.

int a=25;
int b=30;
{ //at this point, a=25, b=30
     a*=2; //a=50, b=30
     b /= 2; //a=50,b=15
     int a = b*b; //a=225,b=15  <--- this new a it's
                  //                 declared on the inner scope
}
//a = 50, b = 15

ANSIC로 제한된 경우 변수를 사용하는 위치에 더 가까운 변수를 선언하는 데 사용할 수 있습니다.

int main() {
    /* Blah blah blah. */
    {
        int i;
        for (i = 0; i < 10; ++i) {
        }
    }
}

그러나 현대의 C 컴파일러에는 필요하지 않습니다.

유용한 사용-캐시모는 C++에서 중요한 섹션을 정의하는 것입니다. 예:

int MyClass::foo()
{    
   // stuff uncritical for multithreading
   ...
   {
      someKindOfScopeLock lock(&mutexForThisCriticalResource);
      // stuff critical for multithreading!
   }
   // stuff uncritical for multithreading
   ...    
}

익명 범위를 사용하면 뮤텍스 또는 세마포의 잠금/잠금 해제를 명시적으로 호출할 필요가 없습니다.

임시 변수가 필요한 코드 블록에 사용합니다.

한 가지 언급할 것은 범위가 컴파일러 제어 현상이라는 것입니다.변수가 범위를 벗어나더라도(그리고 컴파일러가 모든 소멸자를 호출하고 POD 유형이 코드에 즉시 최적화됨), 변수는 스택에 남아 있고 상위 범위에 정의된 새로운 변수는 gcc 또는 clang에 덮어쓰지 않습니다(-Ofast로 컴파일하는 경우에도).변수가 컴파일러 수준에서 개념적으로 범위를 벗어났기 때문에 주소를 통해 변수에 액세스하는 것은 정의되지 않은 동작이라는 점을 제외하면 컴파일러는 식별자로 변수에 액세스하는 것을 중지합니다.

#include <stdio.h>
int main(void) {
  int* c;
  {
    int b = 5; 
    c=&b;
  }
  printf("%d", *c); //undefined behaviour but prints 5 for reasons stated above
  printf("%d", b); //compiler error, out of scope
  return 0;
}

또한 모든 경우 조건에 따라 한 블록 또는 다른 블록을 실행하는 익명 블록(예: 복합 문) 앞에 있습니다.

언급URL : https://stackoverflow.com/questions/500006/what-is-the-purpose-of-anonymous-blocks-in-c-style-languages

반응형

'code' 카테고리의 다른 글

TypeScript에서 React 구성 요소 확장  (0) 2023.06.12
C의 2D 배열 포인터  (0) 2023.06.12
선형 회귀 분석 및 R 단위로 그룹화  (0) 2023.06.12
가상 환경 복제 방법  (0) 2023.06.12
attr_accessor와 attr_accessible의 차이  (0) 2023.06.12