C return в конструкторе

Обновлено: 07.05.2024

Метод может возвращать значение, какой-либо результат. В примере выше были определены два метода, которые имели тип void . Методы с таким типом не возвращают никакого значения. Они просто выполняют некоторые действия.

Но методы также могут возвращать некоторое значение. Для этого применяется оператор return , после которого идет возвращаемое значение:

Например, определим метод, который возвращает значение типа string :

Метод GetMessage имеет тип string , следовательно, он должен возвратить строку. Поэтому в теле метода используется оператор return , после которого указана возвращаемая строка.

При этом методы, которые в качестве возвращаемого типа имеют любой тип, кроме void , обязательно должны использовать оператор return для возвращения значения. Например, следующее определение метода некорректно:

Также между возвращаемым типом метода и возвращаемым значением после оператора return должно быть соответствие. Например, в следующем случае возвращаемый тип - string , но метод возвращает число (тип int), поэтому такое определение метода некорректно:

Результат методов, который возвращают значение, мы можем присвоить переменным или использовать иным образом в программе:

Метод GetMessage() возвращает значение типа string . Поэтому мы можем присвоить это значение какой-нибудь переменной типа string: string message = GetMessage();

Либо даже передать в качестве значения параметру другого метода:

В вызове PrintMessage(GetMessage()) сначада вызывается метод GetMessage() и его результат передается параметру message метода PrintMessage

После оператора return также можно указывать сложные выражения или вызовы других методов, которые возвращают определенный результат. Например, определим метод, который возвращает сумму чисел:

Метод Sum() имеет тип int , следовательно, он должен возвратить значение типа int - целое число. Поэтому в теле метода используется оператор return , после которого указано возвращаемое число (в данном случае результат суммы переменных x и y).

Сокращенная версия методов с результатом

Также мы можем сокращать методы, которые возвращают значение:

аналогичен следующему методу:

аналогичен следующему методу:

Выход из метода

Оператор return не только возвращает значение, но и производит выход из метода. Поэтому он должен определяться после остальных инструкций. Например:

С точки зрения синтаксиса данный метод корректен, однако его инструкция Console.WriteLine("After return") не имеет смысла - она никогда не выполнится, так как до ее выполнения оператор return возвратит значение и произведет выход из метода.

Однако мы можем использовать оператор return и в методах с типом void . В этом случае после оператора return не ставится никакого возвращаемого значения (ведь метод ничего не возвращает). Типичная ситуация - в зависимости от опеределенных условий произвести выход из метода:

Однако если возраст корректен, то выводим информацию о пользователе на консоль. Консольный вывод:

My question is what does a constructor return? This question is not quite different from "What is the return type of a constructor?" I have read somewhere that a constructor returns a complete object implicitly (i.e implicit return type is the name of the class) but it shall not be specified explicitly.

So as per my interpretation the implicit return type should be the name of the class, in this case empty . Is my wild interpretation correct?

Well, when you call new Class(); , it returns a pointer to the location of that instance of the class. Is that what you are referring to?

6 Answers 6

A constructor doesn't return anything. A constructor is called to initialize an object. A constructor can only be used to initialize an object; you can't actually call a constructor explicitly (for one thing, constructors do not have names).

In the example you give, empty() is not a function call expression, it is value initialization. It creates a value-initialized temporary object of type empty .

@Invisible: The important part of that statement is "in a sense:" that's not exactly what happens and it's not strictly correct, but it's a good way of thinking about constructors and initialization.

Adding to "you can't actually call a constructor" - sometimes, there's a reason to want to construct an object in memory that has already been allocated. The idea of an explicit call to a constructor may be compelling - but in fact even that doesn't work. The "placement new" syntax is used instead. Though in a slight asymmetry, the cleanup action that complements this (destruct the object but don't free the memory) is an explicit destructor call - not a "placement delete".

An extra thought - within the constructor (as with any method) the object is referenced via the this implicit parameter. The pointer to the instance (or rather uninitialised memory) is passed in, not returned out. Though of course the references via this are usually as implicit as the parameter itself.

@doc: Yes. It constructs a temporary Terminator object, calls Terminator::say() on that temporary object, then destroys that temporary object. Temporary objects are not destroyed until the end of the full expression in which they were constructed.

construct does return something. it returns reference to object that this points to. so the implicit return statement from a constructor looks like

How is this used?

If you create a class template of something with a "generic" type as member, you call the default zero parameter constructor of the generic type explicitly (i.e., generic() ) in the constructor of your class something and initialize your generic member via the assignment operator and initialization statement of the something constructor. Constructor has to return something or none of that crap I just wrote would work. It's in the book I'm reading. lol.

What if I write return statement in constructor? Is it standard conformant?

The above code compiles fine, without any error at ideone. But the following code doesn't:

It gives this error at ideone:

error: returning a value from a constructor

I understand that returning value from constructor doesn't make sense at all, because it doesn't explicitly mention return type, and we cannot store the returned value after all. But I'm curious to know :

  • Which statement from the C++ Standard allows the first example but forbids the second one? Is there any explicit statement?
  • Is the return type in the first example void ?
  • Is there any implicit return type at all?

I'm not going to voluntarily reread the standard, but I'll venture a guess regarding the motivation for allowing an empty return: if a constructor has branches or loops, then sometimes it is nice to be able to return out. If return was never allowed, then developers would probably just goto to a label defined at the bottom of the function.

2 Answers 2

Yes, using return statements in constructors is perfectly standard.

Constructors are functions that do not return a value. The family of functions that do not return a value consists of: void functions, constructors and destructors. It is stated in 6.6.3/2 in the C++ standard. The very same 6.6.3/2 states that it is illegal to use return with an argument in a function that does not return a value.

6.6.3 The return statement

2 A return statement without an expression can be used only in functions that do not return a value, that is, a function with the return type void, a constructor (12.1), or a destructor (12.4). A return statement with an expression of non-void type can be used only in functions returning a value; the value of the expression is returned to the caller of the function.

Additionally, 12.1/12 states that

12.1 Constructors

12 No return type (not even void) shall be specified for a constructor. A return statement in the body of a constructor shall not specify a return value.

Note, BTW, that in C++ it is legal to use return with an argument in a void function, as long as the argument of return has type void

This is not allowed in constructors though, since constructors are not void functions.

There's also one relatively obscure restriction relevant to the usage of return with constructors: it is illegal to use return in function-try-block of a constructor (with other functions it is OK)

15.3 Handling an exception

15 If a return statement appears in a handler of the function-try-block of a constructor, the program is ill formed.

Оператор return завершает выполнение функции и возвращает управление вызывающей функции. Выполнение возобновляется в вызывающей функции в точке сразу после вызова. Оператор return может возвращать значение, передавая его вызывающей функции. Дополнительные сведения см. в статье Тип возвращаемого значения.

Синтаксис

оператор-перехода:
return expressionopt ;

Значение параметра выражение, если оно указано, возвращается вызывающей функции. Если параметр выражение опущен, возвращаемое значение функции не определено. Параметр "выражение", если он присутствует, вычисляется и преобразуется к типу, возвращаемому функцией. Если оператор return содержит выражение в функциях, имеющих тип возвращаемого значения void , то компилятор выдает предупреждение, а выражение не вычисляется.

В качестве лучшей методики разработки рекомендуется всегда указывать тип возвращаемого значения для ваших функций. Если возвращаемое значение не требуется, объявите функцию как имеющую тип возвращаемого значения void . Если тип возвращаемого значения не указан, компилятор C предполагает, что по умолчанию используется тип возвращаемого значения int .

Многие программисты заключают аргумент выражения в выражении return в скобки. Однако использовать эти скобки в языке C необязательно.

В функции main оператор return и выражение являются необязательными. То, что происходит с указанным возвращаемым значением, зависит от реализации. Только для Майкрософт:реализация C от Майкрософт возвращает значение выражения процессу, вызвавшему программу, например cmd.exe . Если выражение return не указано, среда выполнения C от Майкрософт возвращает значение, соответствующее успешному (0) или неудачному (ненулевое значение) выполнению.

Пример

В этом примере показана одна программа из нескольких частей. Она демонстрирует оператор return и использование его для завершения выполнения функции и, при необходимости, возврата какого-то значения.

Функция square возвращает квадрат своего аргумента, используя более широкий тип для избежания арифметической ошибки. Только для систем Майкрософт: в реализации C от Майкрософт тип long long достаточно велик, чтобы вмещать произведение двух значений int без переполнения.

Скобки вокруг выражения return в функции square вычисляются как часть выражения, и использовать их в операторе return не требуется.

Функция ratio возвращает частное двух int аргументов в виде значения double с плавающей запятой. Выражение return принудительно использует операцию с плавающей запятой путем приведения одного из операндов к типу double . В противном случае будет использоваться оператор целочисленного деления, а дробная часть будет потеряна.

Функция report_square вызывает square со значением параметра INT_MAX — самым большим целым числом со знаком, которое помещается в int . Результат типа long long сохраняется в squared , а затем выдается в выводе. Функция report_square имеет тип возвращаемого значения void , поэтому она не содержит выражения в операторе return .

Функция report_ratio вызывает ratio со значениями параметров 1 и INT_MAX . Результат типа double сохраняется в fraction , а затем выдается в выводе. Функция report_ratio имеет тип возвращаемого значения void , поэтому явно возвращать значение не требуется. Выполнение report_ratio не дает результата и не возвращает вызывающей функции никакого значения.

Функция main вызывает две функции: report_square и report_ratio . Поскольку report_square не принимает параметров и возвращает void , результат не присваивается переменной. Аналогичным образом функция report_ratio возвращает void , поэтому ее возвращаемое значение тоже не сохраняется. После вызова каждой из этих функций выполнение продолжается в следующем операторе. Затем main возвращает значение 0 (обычно свидетельствующее об успешном выполнении), чтобы завершить программу.

Чтобы скомпилировать пример, создайте файл исходного кода с именем C_return_statement.c . Затем скопируйте весь пример кода в показанном здесь порядке. Сохраните файл и скомпилируйте его в окне Командной строки разработчика с помощью следующей команды:

cl /W4 C_return_statement.c

После этого, чтобы запустить пример кода, введите C_return_statement.exe в командной строке. Выходные данных в этом примере выглядят следующим образом:

A return statement ends the execution of a function, and returns control to the calling function. Execution resumes in the calling function at the point immediately following the call. A return statement can return a value to the calling function. For more information, see Return type.

Syntax

The value of expression, if present, is returned to the calling function. If expression is omitted, the return value of the function is undefined. The expression, if present, is evaluated and then converted to the type returned by the function. When a return statement contains an expression in functions that have a void return type, the compiler generates a warning, and the expression isn't evaluated.

If no return statement appears in a function definition, control automatically returns to the calling function after the last statement of the called function is executed. In this case, the return value of the called function is undefined. If the function has a return type other than void , it's a serious bug, and the compiler prints a warning diagnostic message. If the function has a void return type, this behavior is okay, but may be considered poor style. Use a plain return statement to make your intent clear.

As a good engineering practice, always specify a return type for your functions. If a return value isn't required, declare the function to have void return type. If a return type isn't specified, the C compiler assumes a default return type of int .

Many programmers use parentheses to enclose the expression argument of the return statement. However, C doesn't require the parentheses.

The compiler may issue a warning diagnostic message about unreachable code if it finds any statements placed after the return statement.

In a main function, the return statement and expression are optional. What happens to the returned value, if one is specified, depends on the implementation. Microsoft-specific: The Microsoft C implementation returns the expression value to the process that invoked the program, such as cmd.exe . If no return expression is supplied, the Microsoft C runtime returns a value that indicates success (0) or failure (a non-zero value).

Example

This example is one program in several parts. It demonstrates the return statement, and how it's used both to end function execution, and optionally, to return a value.

The square function returns the square of its argument, in a wider type to prevent an arithmetic error. Microsoft-specific: In the Microsoft C implementation, the long long type is large enough to hold the product of two int values without overflow.

The parentheses around the return expression in square are evaluated as part of the expression, and aren't required by the return statement.

The ratio function returns the ratio of its two int arguments as a floating-point double value. The return expression is forced to use a floating-point operation by casting one of the operands to double . Otherwise, the integer division operator would be used, and the fractional part would be lost.

The report_square function calls square with a parameter value of INT_MAX , the largest signed integer value that fits in an int . The long long result is stored in squared , then printed. The report_square function has a void return type, so it doesn't have an expression in its return statement.

The report_ratio function calls ratio with parameter values of 1 and INT_MAX . The double result is stored in fraction , then printed. The report_ratio function has a void return type, so it doesn't need to explicitly return a value. Execution of report_ratio "falls off the bottom" and returns no value to the caller.

The main function calls two functions: report_square and report_ratio . As report_square takes no parameters and returns void , we don't assign its result to a variable. Likewise, report_ratio returns void , so we don't save its return value, either. After each of these function calls, execution continues at the next statement. Then main returns a value of 0 (typically used to report success) to end the program.

To compile the example, create a source code file named C_return_statement.c . Then, copy all the example code, in the order shown. Save the file, and compile it in a Developer command prompt window by using the command:

cl /W4 C_return_statement.c

Then, to run the example code, enter C_return_statement.exe at the command prompt. The output of the example looks like this:

Читайте также: