program tip

const는 C / C ++에서 어떤 종류의 최적화를 제공합니까?

radiobox 2020. 12. 13. 09:10
반응형

const는 C / C ++에서 어떤 종류의 최적화를 제공합니까?


가독성을 위해 참조 나 포인터로 매개 변수를 전달할 때 가능한 한 const 키워드를 사용해야한다는 것을 알고 있습니다. 인수가 상수임을 지정하면 컴파일러가 수행 할 수있는 최적화가 있습니까?

다음과 같은 몇 가지 경우가있을 수 있습니다.

기능 매개 변수 :

상수 참조 :

void foo(const SomeClass& obj)

상수 SomeClass 객체 :

void foo(const SomeClass* pObj)

SomeClass에 대한 상수 포인터 :

void foo(SomeClass* const pObj)

변수 선언 :

const int i = 1234

함수 선언 :

const char* foo()

각각은 어떤 종류의 컴파일러 최적화를 제공합니까 (있는 경우)?


[독자들은이 게시물의 대부분이 Herb Sutter ( http://www.gotw.ca/gotw/081.htm-OP의 저작자 표시 없음) 의 기사에서 발췌 되었습니다.]

CASE_1 :-

프로그램에서 const를 선언하면

int const x = 2;

컴파일러는이 변수에 스토리지를 제공하지 않고 심볼 테이블에 추가함으로써이 const를 최적화 할 수 있습니다. 따라서 후속 읽기는 메모리에서 값을 가져 오는 명령이 아니라 기호 테이블에 대한 간접적 인 작업 만 필요합니다.

참고 :-아래와 같이하면 :-

const int x = 1;
const int* y = &x;

그러면 컴파일러가 'x'. 따라서이 경우에는 그 정도의 최적화가 불가능합니다.

함수 매개 const변수는 매개 변수가 함수에서 수정되지 않음을 의미합니다. 내가 아는 한, 사용에 대한 실질적인 성능 향상은 없지만 const정확성을 보장하는 수단입니다.

CASE_2 :-

"매개 변수 및 / 또는 반환 값을 const로 선언하면 컴파일러가보다 최적의 코드를 생성하는 데 도움이됩니까?"

  const Y& f( const X& x )
  {
    // ... do something with x and find a Y object ...
    return someY;
  }

Ques => 컴파일러가 더 잘할 수있는 것은 무엇입니까?

=> 매개 변수 또는 반환 값의 복사를 피할 수 있습니까?

아니요, 인수는 이미 참조로 전달되었습니다.

=> x 또는 someY의 복사본을 읽기 전용 메모리에 넣을 수 있습니까?

아니요, x와 someY는 모두 범위 밖에서 살고 외부 세계에서 오거나 외부 세계에 주어지기 때문입니다. someY가 f () 자체 내에서 동적으로 동적으로 할당 되더라도 그것과 그 소유권은 호출자에게 넘겨집니다.

Ques => f () 본문에 나타나는 코드의 가능한 최적화는 어떻습니까? const 때문에 컴파일러가 f () 본문에 대해 생성하는 코드를 어떻게 든 개선 할 수 있습니까?

const 멤버 함수를 호출하더라도 컴파일러는 개체 x 또는 개체 someY의 비트가 변경되지 않을 것이라고 가정 할 수 없습니다. 또한 추가 문제가 있습니다 (컴파일러가 전역 최적화를 수행하지 않는 한) : 컴파일러는 또한 다른 코드가 x 및 / 또는 someY와 동일한 객체를 별칭으로 지정하는 상수가 아닌 참조를 갖고 있지 않은지, 그리고 그러한 것이 있는지 알지 못할 수도 있습니다. 동일한 객체에 대한 상수가 아닌 참조는 f () 실행 중에 우연히 사용될 수 있습니다. 그리고 컴파일러는 x와 someY가 단지 참조 인 실제 객체가 처음에 실제로 const로 선언되었는지조차 알지 못할 수도 있습니다.

CASE_3 :-

  void f( const Z z )
  {
    // ...
  }

Ques => 이것에 최적화가 있습니까?

예, 컴파일러는 z가 진정으로 const 객체라는 것을 알고 있기 때문에 전역 분석 없이도 유용한 최적화를 수행 할 수 있습니다. 예를 들어 f ()의 본문에 g (& z)와 같은 호출이 포함 된 경우 컴파일러는 z의 변경 불가능한 부분이 g () 호출 중에 변경되지 않도록 할 수 있습니다.


대답을하기 전에, 사용하거나 사용하지 않는 이유 const는 컴파일러 최적화보다는 프로그램의 정확성과 다른 개발자의 명확성을위한 것이어야 한다는 점을 강조하고 싶습니다 . 즉, const메소드가 해당 매개 변수를 수정하지 않을 매개 변수 문서를 const작성하고 해당 구성원이 구성원 인 오브젝트를 수정하지 않을 것임을 구성원 함수 문서로 작성하십시오 (적어도 임의의 출력을 논리적으로 변경하는 방식은 아닙니다). 다른 const 멤버 함수). 예를 들어, 이렇게하면 개발자가 불필요한 객체 사본을 만들지 않거나 (원본이 파괴되거나 수정 될 것이라고 걱정할 필요가 없기 때문에) 불필요한 스레드 동기화를 피할 수 있습니다 (예 : 모든 스레드가 단순히 읽고 문제의 개체를 변경하지 마십시오).

최적화 측면에서 컴파일러는 적어도 이론적으로는 표준 C ++ 코드를 깨뜨릴 수있는 특정 비표준 가정을 만들 수있는 최적화 모드에서 만들 수 있지만 다음을 고려하십시오.

for (int i = 0; i < obj.length(); ++i) {
   f(obj);
}

length함수가로 표시 const되었지만 실제로는 비용이 많이 드는 작업이라고 가정합니다 (실제로 O (1) 시간 대신 O (n) 시간에 작동 한다고 가정 해 보겠습니다). 함수 f가 매개 변수를 const참조로 사용하는 경우 컴파일러는 잠재적으로이 루프를 다음과 같이 최적화 할 수 있습니다.

int cached_length = obj.length();
for (int i = 0; i < cached_length; ++i) {
   f(obj);
}

... because the fact that the function f does not modify the parameter guarantees that the length function should return the same values each time given that the object has not changed. However, if f is declared to take the parameter by a mutable reference, then length would need to be recomputed on each iteration of the loop, as f could have modified the object in a way to produce a change in the value.

As pointed out in the comments, this is assuming a number of additional caveats and would only be possible when invoking the compiler in a non-standard mode that allows it to make additional assumptions (such as that const methods are strictly a function of their inputs and that optimizations can assume that code will never use const_cast to convert a const reference parameter to a mutable reference).


Function parameters:

const is not significant for referenced memory. It's like tying a hand behind the optimizer's back.

Suppose you call another function (e.g. void bar()) in foo which has no visible definition. The optimizer will have a restriction because it has no way of knowing whether or not bar has modified the function parameter passed to foo (e.g. via access to global memory). Potential to modify memory externally and aliasing introduce significant restrictions for optimizers in this area.

Although you did not ask, const values for function parameters does allow optimizations because the optimizer is guaranteed a const object. Of course, the cost to copy that parameter may be much higher than the optimizer's benefits.

See: http://www.gotw.ca/gotw/081.htm


Variable declarations: const int i = 1234

This depends on where it is declared, when it is created, and the type. This category is largely where const optimizations exist. It is undefined to modify a const object or known constant, so the compiler is allowed to make some optimizations; it assumes you do not invoke undefined behavior and that introduces some guarantees.

const int A(10);
foo(A);
// compiler can assume A's not been modified by foo

Obviously, an optimizer can also identify variables which do not change:

for (int i(0), n(10); i < n; ++i) { // << n is not const
 std::cout << i << ' ';
}

Function declarations: const char* foo()

Not significant. The referenced memory may be modified externally. If the referenced variable returned by foo is visible, then an optimizer could make an optimization, but that has nothing to do with the presence/absence of const on the function's return type.

Again, a const value or object is different:

extern const char foo[];


SomeClass* const pObj creates a constant object of pointer type. There exists no safe method of changing such an object, so the compiler can, for example, cache it into a register with only one memory read, even if its address is taken.

The others don't enable any optimizations specifically, although the const qualifier on the type will affect overload resolution and possibly result in different and faster functions being selected.


The exact effects of const differ for each context where it is used. If const is used while declaring an variable, it is physically const and potently resides in read-only memory.

const int x = 123;

Trying to cast the const-ness away is undefined behavour:

Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior. cppreference/const_cast

So in this case, the compiler may assume that the value of x is always 123. This opens some optimization potential (constants propagation)

For functions it's a different matter. Suppose:

void doFancyStuff(const MyObject& o);

our function doFancyStuff may do any of the following things with o.

  1. not modify the object.
  2. cast the constness away, then modify the object
  3. modify an mutable data member of MyObject

Note that if you call our function with an instance of MyObject that was declared as const, you'll invoke undefined behavior with #2.

Guru question: will the following invoke undefined behavior?

const int x = 1;
auto lam = [x]() mutable {const_cast<int&>(x) = 2;};
lam();

참고URL : https://stackoverflow.com/questions/27466642/what-kind-of-optimization-does-const-offer-in-c-c

반응형