Namespaces
Variants

Default arguments

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

함수가 하나 이상의 후행 인수를 제공하지 않고 호출될 수 있도록 합니다.

함수 선언의 매개변수 목록 에서 매개변수에 대해 다음 구문을 사용하여 표시됩니다.

attr  (선택 사항) decl-specifier-seq declarator = initializer (1)
attr  (선택 사항) decl-specifier-seq abstract-declarator  (선택 사항) = initializer (2)

기본 인수는 함수 호출에서 누락된 후행 인수 대신 사용됩니다:

void point(int x = 3, int y = 4);
point(1, 2); // point(1, 2)를 호출합니다
point(1);    // point(1, 4)를 호출합니다
point();     // point(3, 4)를 호출합니다

함수 선언에서 기본 인수를 가진 매개변수 뒤에 오는 모든 후속 매개변수는 다음을 충족해야 합니다:

  • 이 범위 또는 동일한 범위의 이전 선언에서 제공된 기본 인수를 가짐:
int x(int = 1, int); // 오류: 오직 후행 매개변수만 기본 인자를 가질 수 있음
                     //        ("x"의 이전 선언이 없다고 가정할 때)
void f(int n, int k = 1);
void f(int n = 0, int k); // 정상: "k"의 기본 인자는 동일한 범위의
                          // 이전 선언에서 제공됨
void g(int, int = 7);
void h()
{
    void g(int = 1, int); // 오류: 동일한 범위가 아님
}
  • ...매개변수가 매개변수 팩에서 확장된 경우가 아니면:
template<class... T>
struct C { void f(int n = 0, T...); };
C<int> c;  // OK; instantiates declaration void C::f(int n = 0, int)
  • 또는 함수 매개변수 팩인 경우:
template<class... T>
void h(int i = 0, T... args); // OK
(C++11부터)

생략 부호는 매개변수가 아니므로 기본 인수가 있는 매개변수 뒤에 올 수 있습니다:

int g(int n = 0, ...); // 정상

기본 인수는 함수 선언 람다 표현식 의 매개변수 목록에서만 허용되며, (C++11부터) 함수 포인터, 함수 참조 선언이나 typedef 선언에서는 허용되지 않습니다. 템플릿 매개변수 목록은 기본 템플릿 인수 에 대해 유사한 구문을 사용합니다.

비템플릿 함수의 경우, 동일한 스코프에서 함수가 재선언되면 이미 선언된 함수에 기본 인자를 추가할 수 있습니다. 함수 호출 시점에서 기본 인자는 해당 함수에 대해 표시되는 모든 선언에서 제공된 기본 인자의 합집합입니다. 재선언은 이미 표시되는 기본 인자가 있는 매개변수에 대해 기본 인자를 도입할 수 없습니다(값이 동일한 경우에도). 내부 스코프에서의 재선언은 외부 스코프의 기본 인자를 상속받지 않습니다.

void f(int, int);     // #1
void f(int, int = 7); // #2 OK: 기본 인수를 추가함
void h()
{
    f(3); // #1과 #2가 스코프 내에 있음; f(3,7) 호출을 수행함
    void f(int = 1, int); // 오류: 두 번째 매개변수의 기본 인수가
                          // 외부 스코프에서 상속되지 않음
}
void m()
{ // 새로운 스코프 시작
    void f(int, int); // 내부 스코프 선언; 기본 인수가 없음.
    f(4); // 오류: f(int, int)를 호출하기에 인수가 부족함
    void f(int, int = 6);
    f(4); // OK: f(4, 6) 호출;
    void f(int, int = 6); // 오류: 두 번째 매개변수는 이미
                          // 기본 인수를 가지고 있음 (값이 동일하더라도)
}
void f(int = 1, int); // #3 OK, #2에 기본 인수를 추가함
void n()
{ // 새로운 스코프 시작
    f(); // #1, #2, #3이 스코프 내에 있음: f(1, 7) 호출;
}

만약 inline 함수가 다른 번역 단위에서 선언된다면, 기본 인자들의 누적 집합은 각 번역 단위의 끝에서 반드시 동일해야 합니다.

인라인이 아닌 함수가 다른 번역 단위에서 동일한 네임스페이스 범위로 선언된 경우, 해당 기본 인수(기본 인자가 존재한다면)는 동일해야 합니다(단, 일부 번역 단위에서는 일부 기본 인수가 없을 수 있습니다).

(since C++20)

만약 friend 선언이 기본 인수를 지정한다면, 이것은 friend 함수 정의여야 하며, 이 함수의 다른 선언은 번역 단위에서 허용되지 않습니다.

using 선언 은 알려진 기본 인수 집합을 이전하며, 나중에 함수의 네임스페이스에 더 많은 기본 인수가 추가되면, 해당 기본 인수들도 using 선언이 보이는 모든 곳에서 보입니다:

namespace N
{
    void f(int, int = 1);
}
using N::f;
void g()
{
    f(7); // f(7, 1)를 호출합니다;
    f();  // 오류
}
namespace N
{
    void f(int = 2, int);
}
void h()
{
    f();  // f(2, 1)를 호출합니다;
}

기본 인수에 사용된 이름들은 선언 시점에서 조회되고, 접근성 을 확인하며 바인딩되지만, 함수 호출 시점에서 실행됩니다:

int a = 1;
int f(int);
int g(int x = f(a)); // f 탐색은 ::f를 찾고, a 탐색은 ::a를 찾음
                     // 이 시점에서 값이 1인 ::a의 값은 사용되지 않음
void h()
{
    a = 2; // ::a의 값을 변경
    {
        int a = 3;
        g(); // f(2)를 호출한 후, 그 결과로 g()를 호출
    }
}

비- 멤버 함수 가 아닌 템플릿화된 클래스의 멤버 함수의 경우, 기본 인수는 클래스 외부 정의에서 허용되며, 클래스 본문 내 선언에서 제공된 기본 인수와 결합됩니다. 만약 이러한 클래스 외부 기본 인수가 멤버 함수를 기본 생성자나 복사 /이동 (C++11부터) 생성자/대입 연산자로 변환하는 경우(호출을 모호하게 만듦), 프로그램은 형식에 맞지 않습니다. 템플릿화된 클래스의 멤버 함수의 경우, 모든 기본 인수는 멤버 함수의 최초 선언에서 제공되어야 합니다.

class C
{
    void f(int i = 3);
    void g(int i, int j = 99);
    C(int arg); // 기본 생성자가 아닌 생성자
};
void C::f(int i = 3) {}         // 오류: 기본 인수가 이미
                                // 클래스 범위에서 지정됨
void C::g(int i = 88, int j) {} // OK: 이 번역 단위에서,
                                // C::g는 인수 없이 호출 가능
C::C(int arg = 1) {}            // 오류: 이를 기본 생성자로 변환함

virtual 함수의 재정의자는 기본 클래스 선언에서 기본 인수를 상속받지 않으며, 가상 함수 호출이 발생할 때 기본 인수는 객체의 정적 타입을 기반으로 결정됩니다(참고: 이는 non-virtual interface 패턴으로 회피할 수 있습니다).

struct Base
{
    virtual void f(int a = 7);
};
struct Derived : Base
{
    void f(int a) override;
};
void m()
{
    Derived d;
    Base& b = d;
    b.f(); // 정상: Derived::f(7) 호출
    d.f(); // 오류: 기본 인자가 없음
}

기본 인수에서는 지역 변수가 허용되지 않습니다. 단, 평가되지 않는 경우 는 예외입니다:

void f()
{
    int n = 1;
    extern void g(int x = n); // 오류: 지역 변수는 기본 인수로 사용할 수 없음
    extern void h(int x = sizeof n); // CWG 2082부터 허용됨
}

this 포인터는 기본 인수에서 허용되지 않습니다:

class A
{
    void f(A* p = this) {} // 오류: 허용되지 않음
};

비정적 클래스 멤버는 기본 인수에서 허용되지 않습니다(평가되지 않는 경우에도). 단, 멤버에 대한 포인터를 형성하거나 멤버 접근 표현식에서 사용되는 경우는 예외입니다:

int b;
class X
{
    int a;
    int mem1(int i = a); // 오류: 비정적 멤버를 사용할 수 없음
    int mem2(int i = b); // OK: 조회 결과 X::b 정적 멤버를 찾음
    int mem3(int X::* i = &X::a); // OK: 비정적 멤버를 사용할 수 있음
    int mem4(int i = x.a); // OK: 멤버 접근 표현식 내에서
    static X x;
    static int b;
};

기본 인수는 해당 매개변수에 대한 인수 없이 함수가 호출될 때마다 평가됩니다. 함수 매개변수는 평가되지 않는 경우 를 제외하고는 기본 인수에서 허용되지 않습니다. 매개변수 목록에서 앞쪽에 나타나는 매개변수들이 scope 에 있음에 유의하십시오:

int a;
int f(int a, int b = a); // 오류: 기본 인수에서 사용된 매개변수 a
int g(int a, int b = sizeof a); // CWG 2082 해결 전까지 오류
                                // 해결 후 정상: 평가되지 않은 컨텍스트에서의 사용은 허용됨

기본 인수는 함수 타입의 일부가 아닙니다:

int f(int = 0);
void h()
{
    int j = f(1);
    int k = f(); // f(0) 호출;
}
int (*p1)(int) = &f;
int (*p2)()    = &f; // 오류: f의 타입은 int(int)

함수 호출 연산자 첨자 연산자 (C++23부터) 를 제외한 다른 연산자 함수들은 기본 인수를 가질 수 없습니다:

class C
{
    int operator++(int i = 0); // 잘못된 형식
    int operator[](int j = 0); // C++23부터 허용됨
    int operator()(int k = 0); // 허용됨
};

명시적 객체 매개변수 는 기본 인수를 가질 수 없습니다:

struct S { void f(this const S& = S{}); }; // ill-formed
(C++23부터)

참고

매개변수 이름이 없는 경우 복합 할당 토큰을 피하기 위해 공백이 필요할 수 있습니다( maximal munch 참조).

void f1(int*=0);         // 오류: 여기서 "*="는 예상치 못한 토큰입니다
void g1(const int&=0);   // 오류: 여기서 "&="는 예상치 못한 토큰입니다
void f2(int* = 0);       // 정상
void g2(const int& = 0); // 정상
void h(int&&=0);         // 공백 없어도 정상, "&&"는 여기서 토큰입니다

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 217 C++98 클래스 템플릿의 비템플릿 멤버 함수에
기본 인자를 추가할 수 있었음
금지됨
CWG 1344 C++98 멤버 함수의 클래스 외부 정의에서 추가된 기본 인자가
특수 멤버 함수로 변경될 수 있었음
금지됨
CWG 1716 C++98 기본 인자는 호출자가 인자를 제공한 경우에도
함수가 호출될 때마다 평가됨
해당 매개변수에 대한 인자가
제공되지 않은 경우에만
평가됨
CWG 2082 C++98 기본 인자가 비평가 문맥에서 지역 변수와
선행 매개변수를 사용하는 것이 금지됨
비평가 문맥에서의
사용이 허용됨
CWG 2233 C++11 매개변수 팩에서 확장된 매개변수가 기본 인자가 있는
매개변수 뒤에 나타날 수 없었음
허용됨
CWG 2683 C++98 클래스 템플릿의 중첩 클래스 멤버 함수의
클래스 외부 정의에 기본 인자가 있을 수 있었음
금지됨