c++ string 클래스의 원리에 있어 궁금한 것이 있습니다.

익명 사용자의 이미지

연습으로 string 클래스를 만들어보고 있는데요(아주 기본적인 것들로만요..하하하)

일반적으로 string 클래스를 이용할 때

string str1 = "Happy coding!";

string str2 = "OMG----!";

이렇게만 선언해도 생성자가 호출되는데요. 이걸 구현하려고 생각했더니 연산자 오버로딩밖에 생각이 안나더라고요. 그런데 연산자 오버로딩은 이미 생성된 객체에 한해서 호출되는 것이니 사용할 수가 없겠고 전역함수로 만들까 아니면 static 멤버 함수로 만들까 둘다 해보았지만 nonstatic member라고 컴파일러님께서 말씀해주시더라고요.

제가 생각하는 과정으로는 이해가 가지 않는데 (제가 정의한 string 클래스 이름을 MyString이라고 하겠습니다.)

MyString(const char *str)으로 인식해서 알아서 생성자 호출이 되던데...

즉 정리하자면 저는 MyString str = "My String object"; 가 MyString str("My String object);이 되는 과정을 알고 싶습니다.

익명 사용자의 이미지

변환생성자 (conversion constructor)

 의 이미지

결론부터 먼저 말씀드리면, 그냥 됩니다.
string 클래스에 뭔가 특이한 게 있는 게 아니라, 기본적으로 지원되는 클래스 객체 선언 및 초기화 문법이지요.

결론을 좀 더 풀어 설명드리면,
생성자 MyString(const char *str)가 있기만 하면, 아래 두 선언(및 초기화) 모두 유효하고 같은 기능을 합니다.

MyString str = "My String object";
MyString str("My String object");

결론부터 말씀을 드렸으면 이제 Reasoning을 해야 할 때인데... 오늘따라 C++언어 표준을 뒤적거릴 만한 의욕이 없네요.
나중에 다시 돌아와서 써 보겠습니다. 어쩌면 다른 분이 먼저 써 주실지도.

익명 사용자의 이미지

라이브러리로 제공되는 클래스인 경우 그냥 대입연산자를 통해 객체가 생성된다는 말씀이신가요?

new를 붙이지 않아도 (제가 C++ 초보라서 Integer 클래스가 제공되는지는 모르겠으나)

Integer i = 3; 해도 이것이 Integer i(3); 과 같은 결과를 갖는 건가요?

 의 이미지

라이브러리냐 아니냐가 중요한 것이 아닙니다. 그냥 C++ 객체 초기화 문법의 일부입니다.

1. C++의 Initializers는 크게 나눠서 아래와 같은 세 가지 꼴을 가집니다.
ⅰ. T a = /* something */
ⅱ. T a( /* something */ )
ⅲ. T a{ /* something */ } // since C++11

2. 구체적으로 초기화가 어떻게 되어야 한다고 규정되어 있는지 살펴봅시다.

우선 ⅰ에서는 copy-initialization, ⅱ와 ⅲ에서는 direct-initialization이 일어납니다.
그리고 질문 맥락에 따라 T가 클래스 타입이라고 가정하겠습니다.

(1) direct-initialization인 경우
(2) copy-initialization이지만 제공된 초기값(/* something */)의 타입이 T 혹은 T의 파생 클래스인 경우

위 두 가지 경우에는 쉽게 예상할 수 있는 대로, 호출 가능한 생성자 중 가장 적합[1]한 것을 호출함으로써 초기화가 이루어집니다. 질문자님의 경우에는 MyString(const char *str)가 선택되어 호출되는 것이죠.

(3) 그 외의 경우. 즉 copy-initialization이면서 초기값의 타입이 T도 아니고 T의 파생 클래스도 아닌 경우

이 경우의 동작은, 우선 초기값을 타입 T로 변환할 수 있는 가장 적합[1]한 user-defined conversion sequence를 찾아 변환합니다. explicit이 지정되지 않은 constructors와 conversion functions들이 conversion sequence를 이루게 됩니다. 질문자님의 경우에는, 마찬가지로 MyString(const char *str)가 선택되겠지요.

그 다음에 변환 결과로 생성된 temporary를 초기값 삼아 a를 direct-initialize 하게 됩니다. 보통은 복사 생성자가 호출되겠죠. C++ 11이후라면 이동 생성될 거고요.

다만 여기서 주목해야 할 사항이 하나 더 있습니다.

위에서 보시면 아시겠지만 temporary는 그저 중간과정에 존재할 뿐 딱히 의미가 없습니다. 애초에 주어진 초기값으로 temporary 객체를 만들 수 있었다면, 그냥 a를 바로 만들 수도 있었겠지요. C++ 표준에서는 이런 식의 의미 없는 temporary의 생성과 소멸을 컴파일러가 재량껏 생략해 버릴 수 있도록 허용하고 있습니다. 바로 copy elision이라고 부르는 최적화입니다.

거의 모든 현대 C++ 컴파일러가 위 최적화를 지원하기 때문에, 질문자님의 코드 MyString str = "My String object";는 temporary의 생성을 거치지 않고 str에다가 바로 const char *를 받는 생성자를 호출하게 됩니다. 즉 direct-initialization과 똑같이 실행되는 것이죠.

요약하면,

MyString(const char *str)가 존재하고, string literal로부터 MyString을 생성하는 다른 적합[1]한 방법이 없을 경우

(1) MyString str("My String object);는 direct-initialization이라서,
(2) MyString str = "My String object";는 copy-initialization이고 temporary 생성 및 복사/이동 생성을 거쳐야 하지만 copy elision에 의해,

둘 다 str에 대해 생성자 MyString(const char *str)가 호출되는 식으로 초기화가 이루어집니다.

위와 같은 동작은 C++의 객체 초기화 문법 및 의미론에 따른 것이므로, 초기화하고자 하는 객체에 적절한 생성자가 있기만 하면 그게 C++ 표준 라이브러리의 string이든, 제가 모르는 라이브러리의 Integer이든, 질문자님께서 임의로 만든 MyString이든 상관 없이 똑같이 적용됩니다.

[1] "적합"의 기준은 표준에 아주 상세하게 설명되어 있습니다. Overload resolution이라고 불리는 내용인데, 요약해서 설명드리기에는 너무 길고 복잡해요. 관심 있으시면 직접 찾아서 읽으시길. 사견입니다만, 표준의 overload resolution 메커니즘을 꼭 읽어야만 해석할 수 있을 정도로 복잡한 상황을 만드는 것 자체가 애초에 별로 바람직하지 않다고 봅니다. -_-;;

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.