문제

내가 일하는 곳에서 사람들은 대부분 객체가 C ++-스타일 구성 (괄호 포함)을 사용하여 초기화되는 것이 가장 좋다고 생각하지만, 원시 유형은 = 연산자와 함께 초기화되어야합니다.

std::string strFoo( "Foo" );
int nBar = 5;

그래도 아무도 왜 이런 식으로 사물을 선호하는지 설명 할 수없는 것 같습니다. 나는 그것을 볼 수있다 std::string = "Foo"; 추가 사본이 포함되어 있기 때문에 비효율적이지만, = 운영자는 전적으로 괄호를 사용하고 어디서나 괄호를 사용합니까?

일반적인 협약입니까? 그 뒤에있는 생각은 무엇입니까?

도움이 되었습니까?

해결책

성능과 관련하여 중요하다는 것을 증명하지 않는 한, 나는 당신의 예제에서 할당 연산자를 사용하여 추가 사본을 걱정하지 않을 것입니다.std::string foo = "Foo";). 최적화 된 코드를 보면 해당 사본이 존재한다면 정말 놀랄 것입니다. 실제로 적절한 매개 변수화 된 생성자를 호출 할 것이라고 생각합니다.

귀하의 질문에 대한 답으로, 그렇습니다. 저는 그것이 매우 일반적인 관습이라고 말하고 싶습니다. 고전적으로 사람들은 과제를 사용하여 내장 유형을 초기화했으며 전통을 바꿀 수있는 강력한 이유는 없습니다. 최고의 코드에 미치는 영향이 거의없는 경우,이 컨벤션의 가독성과 습관은 완벽하게 유효한 이유입니다.

다른 팁

= 연산자 또는 생성자 호출로 변수 초기화는 의미 적으로 동일하며 스타일의 문제 일뿐입니다. 더 자연스럽게 읽기 때문에 = 연산자를 선호합니다.

= 연산자 사용 대개 추가 사본을 생성하지 않습니다. 단지 일반 생성자라고합니다. 그러나 비-프림 유형의 경우, 이는 선언과 동시에 발생하는 초기화를위한 것입니다. 비교하다:

std::string strFooA("Foo");  // Calls std::string(const char*) constructor
std::string strFoo = "Foo";  // Calls std::string(const char*) constructor
                             // This is a valid (and standard) compiler optimization.

std::string strFoo;  // Calls std::string() default constructor
strFoo = "Foo";      // Calls std::string::operator = (const char*)

사소한 기본 생성자가 있으면 후자의 구성은 약간 더 비효율적 일 수 있습니다.

그만큼 C ++ 표준, 섹션 8.5, 단락 14 상태 :

그렇지 않으면 (즉, 나머지 사본 초기화 사례의 경우) 임시가 생성됩니다. 소스 유형에서 대상 유형 또는 그 파생 클래스로 변환 할 수있는 사용자 정의 변환 시퀀스는 열거되어 있으며 (13.3.1.4), 가장 좋은 것은 과부하 해상도 (13.3)를 통해 선택됩니다. 선택된 사용자 정의 변환은 이니셜 라이저 표현식을 임시로 변환하기 위해 호출되며,이 유형은 대상 유형의 CV Qualifiers와 함께 사용자 정의 변환 기능의 호출에 의해 반환 된 유형입니다. 변환을 수행 할 수 없거나 모호한 경우 초기화는 잘못 형성됩니다. 초기화되는 객체는 위의 규칙에 따라 임시로부터 직접 시작됩니다.87) 경우에 따라 객체를 직접 초기화하여 임시를 제거 할 수있는 구현이 허용됩니다. 12.2 참조.

섹션 12.2의 일부 :

임시 객체의 생성을 피하면서도 임시 객체가 생성 된 것처럼 모든 의미 론적 제한을 존중해야합니다. [예 : 카피 생성기를 호출하지 않더라도 접근성 (11)과 같은 모든 의미 론적 제한이 충족되어야한다. ]

방금 또 다른 바보 같은 게시물이 필요하다고 느꼈습니다.

string str1 = "foo";

호출됩니다 사본 초기화, 컴파일러가하는 일은 임시를 제외하지 않으면 다음과 같습니다.

string str1(string("foo")); 

사용 된 변환 생성자가 암시 적인지 확인하는 것 외에. 실제로, 모든 암시 적 변환은 사본 초기화 측면에서 표준에 의해 정의됩니다. 유형 U에서 T 형으로의 암시 적 변환이 유효하다고합니다.

T t = u; // u of type U

유효합니다.

구조에서

string str1("foo");

작성된 일을 정확히하고 있으며 직접 초기화. 또한 명백한 생성자와도 작동합니다.

그건 그렇고, -fno-leidide-constructors를 사용하여 임시 자리를 비활성화 할 수 있습니다.

-fno-elide-constructors
    The C++ standard allows an implementation to omit creating a temporary which 
    is only used to initialize another object of the same type. Specifying this 
    option disables that optimization, and forces G++ to call the copy constructor 
    in all cases.

표준은 실제로 차이가 없다고 말합니다

T a = u;

그리고

T a(u);

t와 u의 유형이 원시 유형 인 경우. 따라서 두 형태를 모두 사용할 수 있습니다. 나는 사람들이 두 번째 형태보다 첫 번째 형태를 사용하게하는 것이 단지 그것의 스타일이라고 생각합니다.


어떤 사람들은 선언을 명확하게하고 싶어하기 때문에 어떤 상황에서는 첫 번째를 사용할 수 있습니다.

T u(v(a));

변수의 정의로 누군가를 모색합니다. u 이는 유형의 임시를 사용하여 초기화됩니다 v 그것은 호출 된 생성자의 매개 변수를 얻습니다 a. 그러나 실제로 컴파일러가하는 일은 다음과 같습니다.

T u(v a);

유형의 인수를 취하는 함수 선언을 만듭니다. v, 및 매개 변수가 호출됩니다 a. 그래서 사람들은 그렇게합니다

T u = v(a);

그들이 할 수 있었음에도 불구하고 명백한

T u((v(a)));

또한 함수 매개 변수 주위에 괄호가 없기 때문에 컴파일러는 기능 선언 대신 변수 정의로 읽습니다. :)

당신은 아마도 그와 같은 코드를 찾을 것입니다

std::string strFoo = "Foo";

추가 사본을 수행하지 않고 괄호가있는 것과 동일한 코드 (단일 학습 생성자의 호출)를 컴파일합니다.

반면에 ~ 해야 하다 생성자 멤버 초기화 목록과 같은 괄호를 사용하십시오.

로컬 변수를 구성하기 위해 = 또는 괄호를 사용하는 것이 대부분 개인적인 선택의 문제라고 생각합니다.

글쎄, 누가 무엇을 아는가 그들 생각하지만, 나는 또한 원시 유형의 = 주로 대상이 아니기 때문에, 그리고 그것이 초기화하는 "일반적인"방법이기 때문에 선호합니다.

스타일의 문제입니다. "std :: string ="foo "라는 진술조차도 추가 사본이 포함되어 있기 때문에 비효율적 일 것입니다." 이 "추가 사본"은 컴파일러에 의해 제거됩니다.

나는 그것이 더 습관에 가깝다고 믿는다. 또한 "모든 곳에서 괄호를 사용하여 (언어를 사용할 수있게 함)"라고 말하는 방식이기도합니다.

하나가 할 수있는 한 가지 주장 :

std :: string foo ( "bar");

인수 계수가 변경 되더라도, 즉 :

std :: String foo ( "bar", 5);

'='부호로 작동하지 않습니다.

또 다른 것은 많은 객체의 경우 '='가 부자연 스럽다고 느낀다는 것입니다. 예를 들어 인수가 길이를 제공하는 배열 클래스가 있다고 말합니다.

배열 ARR = 5;

우리는 값 5가있는 배열을 구성하지 않지만 길이 5를 갖기 때문에 기분이 좋지 않습니다.

배열 ARR (5);

값을 복사하는 것이 아니라 주어진 매개 변수로 객체를 구성하고 있기 때문에 더 자연 스럽습니다.

그러나 객체 구문을 사용하여 초기화 목록에서 프리미티브를 초기화하는 것을 훨씬 더 혼동하십시오.

foo::foo()   
  ,anInt(0)   
  ,aFloat(0.0)   
{   
}   
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top