const ref Parameters and const Member Functions - D Programming Language

Menu

- Learn
- Documentation
  - Language Reference
  - Library Reference
  - Command-line Reference
  - Feature Overview
  - Articles
- Downloads
- Packages
- Community
  - Blog
  - Orgs using D
  - Twitter
  - Calendar
  - Discord (community-run)
  - Forums
  - IRC
  - Wiki
  - Issues
  - Contributing
  - Contributors
  - Foundation
  - Security Team
  - Donate
  - Sponsors
- Resources
  - Tour
  - Books
  - Tutorials
  - Tools
  - Editors
  - IDEs
  - run.dlang.io
  - Visual D
  - Acknowledgments
  - D Style
  - Glossary
  - Sitemap

Search
Report a bug
If you spot a problem with this page, click here to create a Bugzilla issue.
Improve this page
Quickly fork, edit online, and submit a pull request for this page. Requires a signed-in GitHub account. This works well for small changes. If you'd like to make larger changes you may want to consider using a local clone.

# const ref Parameters and const Member Functions

This chapter is about how parameters and member functions are marked as `const` so that they can be used with `immutable` variables as well. As we have already covered `const` parameters in earlier chapters, some information in this chapter will be a review of some of the features that you already know.

Although the examples in this chapter use only structs, `const` member functions apply to classes as well.

##### `immutable` objects

We have already seen that it is not possible to modify `immutable` variables:

        immutable readingTime = TimeOfDay(15, 0);

`readingTime` cannot be modified:

        readingTime = TimeOfDay(16, 0);    // ← derleme HATASI
        readingTime.minute += 10;          // ← derleme HATASI

The compiler does not allow modifying `immutable` objects in any way.

##### `ref` parameters that are not `const`

We have seen this concept earlier in the Function Parameters chapter. Parameters that are marked as `ref` can freely be modified by the function. For that reason, even if the function does not actually modify the parameter, the compiler does not allow passing `immutable` objects as that parameter:

    /* Although not being modified by the function, 'duration'
     * is not marked as 'const' */
    int totalSeconds(ref Duration duration) {
        return 60 * duration.minute;
    }
    // ...
        immutable warmUpTime = Duration(3);
        totalSeconds(warmUpTime);    // ← derleme HATASI

The compiler does not allow passing the `immutable` `warmUpTime` to `totalSeconds` because that function does not guarantee that the parameter will not be modified.

##### `const ref` parameters

`const ref` means that the parameter is not modified by the function:

    int totalSeconds(const ref Duration duration) {
        return 60 * duration.minute;
    }
    // ...
        immutable warmUpTime = Duration(3);
        totalSeconds(warmUpTime);    // ← now compiles

Such functions can receive `immutable` objects as parameters because the immutability of the object is enforced by the compiler:

    int totalSeconds(const ref Duration duration) {
        duration.minute = 7;    // ← derleme HATASI
    // ...
    }

An alternative to `const ref` is `in ref`. As we will see in a later chapter, `in` means that the parameter is used only as input to the function, disallowing any modification to it.

    int totalSeconds(in ref Duration duration) {
        // ...
    }

##### Non-`const` member functions

As we have seen with the `TimeOfDay.increment` member function, objects can be modified through member functions as well. `increment()` modifies the members of the object that it is called on:

    struct TimeOfDay {
    // ...
        void increment(Duration duration) {
            minute += duration.minute;

            hour += minute / 60;
            minute %= 60;
            hour %= 24;
        }
    // ...
    }
    // ...
        auto start = TimeOfDay(5, 30);
        start.increment(Duration(30));          // 'start' gets modified

##### `const` member functions

Some member functions do not make any modifications to the object that they are called on. An example of such a function is `toString()`:

    struct TimeOfDay {
    // ...
        string toString() {
            return format("%02s:%02s", hour, minute);
        }
    // ...
    }

Since the whole purpose of `toString()` is to represent the object in string format anyway, it should not modify the object.

The fact that a member function does not modify the object is declared by the `const` keyword after the parameter list:

    struct TimeOfDay {
    // ...
        string toString() const {
            return format("%02s:%02s", hour, minute);
        }
    }

That `const` guarantees that the object itself is not going to be modified by the member function. As a consequence, `toString()` member function is allowed to be called even on `immutable` objects. Otherwise, the struct's `toString()` would not be called:

    struct TimeOfDay {
    // ...
        // Inferior design: Not marked as 'const'
        string toString() {
            return format("%02s:%02s", hour, minute);
        }
    }
    // ...
        immutable start = TimeOfDay(5, 30);
        writeln(start);    // TimeOfDay.toString() is not called!

The output is not the expected `05:30`, indicating that a generic function gets called instead of `TimeOfDay.toString`:

    immutable(TimeOfDay)(5, 30)

Further, calling `toString()` on an `immutable` object explicitly would cause a compilation error:

        auto s = start.toString(); // ← derleme HATASI

Accordingly, the `toString()` functions that we have defined in the previous chapter have all been designed incorrectly; they should have been marked as `const`.

Note: The `const` keyword can be specified before the definition of the function as well:

        // The same as above
        const string toString() {
            return format("%02s:%02s", hour, minute);
        }

Since this version may give the incorrect impression that the `const` is a part of the return type, I recommend that you specify it after the parameter list.

##### `inout` member functions

As we have seen in the Function Parameters chapter, `inout` transfers the mutability of a parameter to the return type.

Similarly, an `inout` member function transfers the mutability of the object to the function's return type:

    import std.stdio;

    struct Container {
        int[] elements;

        inout(int)[] firstPart(size_t n) inout {
            return elements[0 .. n];
        }
    }

    void main() {
        {
            // An immutable container
            auto container = immutable(Container)([ 1, 2, 3 ]);
            auto slice = container.firstPart(2);
            writeln(typeof(slice).stringof);
        }
        {
            // A const container
            auto container = const(Container)([ 1, 2, 3 ]);
            auto slice = container.firstPart(2);
            writeln(typeof(slice).stringof);
        }
        {
            // A mutable container
            auto container = Container([ 1, 2, 3 ]);
            auto slice = container.firstPart(2);
            writeln(typeof(slice).stringof);
        }
    }

The three slices that are returned by the three objects of different mutability are consistent with the objects that returned them:

    immutable(int)[]
    const(int)[]
    int[]

Because it must be called on `const` and `immutable` objects as well, an `inout` member function is compiled as if it were `const`.

##### How to use

- To give the guarantee that a parameter is not modified by the function, mark that parameter as `in`, `const`, or `const ref`.
- Mark member functions that do not modify the object as `const`:

      struct TimeOfDay {
      // ...
          string toString() const {
              return format("%02s:%02s", hour, minute);
          }
      }

  This would make the struct (or class) more useful by removing an unnecessary limitation. The examples in the rest of the book will observe this guideline.

Copyright © 1999-2026 by the D Language Foundation | Page generated by Ddoc on Mon Aug 17 18:57:14 2026