Question

I'm writing an iterator for a new container in c++. When I call begin() and end() functions (both very short), I expected the compiler to make it inline. But it didn't. I think maybe it's because the iterator is returned as a temporary object, and it needs to be copied. I think maybe I can use the RValue reference in c++11, but I'm not familiar with it. So is there a way to make it inline?

The code is something like this (not exactly the same, but I think if this version works, my code will also work)。

I'm using VC++ 2013 CTP, and I have changed compile options but it doesn't work either.

class Pointer
{
public:
    Pointer(int* p) : p(p)
    {
        (*p)++;
    }
    Pointer(const Pointer& pointer) : p(pointer.p)
    {
        (*p)++;
    }
    Pointer& operator =(const Pointer& pointer)
    {
        (*p)--;
        p = pointer.p;
        (*p)++;
    }
    int* p;
    ~Pointer()
    {
        (*p)--;
    }
    static Pointer create(int& p)
    {
        return Pointer(&p);
    }
    static Pointer create2(int& p)
    {
        return create(p);
    }
};

int main()
{
    int p = 0;
    Pointer pointer = Pointer::create2(p);
}

The function create and create2 here are not inline even if, you can see, it's really simple.

I know maybe this doesn't make a difference in the speed of my program, but I just want to have it better.

Was it helpful?

Solution

There are several cases where microsoft's compiler cannot inline functions:

http://msdn.microsoft.com/en-us/library/a98sb923.aspx

In some cases, the compiler will not inline a particular function for mechanical reasons. For example, the compiler will not inline:

A function if it would result in mixing both SEH and C++ EH.

Some functions with copy constructed objects passed by value when -GX/EHs/EHa is on.

Functions returning an unwindable object by value when -GX/EHs/EHa is on.

Functions with inline assembly when compiling without -Og/Ox/O1/O2.

Functions with a variable argument list.

A function with a try (C++ exception handling) statement.

Because the functions return Pointer by value and it has a destructor, the functions cannot be inlined.

There's nothing that can really be done about it other than changing the Pointer class. Rvalue refs don't help here. I would just leave the code as it is and if you need better performance in final product, try another compiler.

RVO may happen here but it doesn't make difference because the cost of copying is so small.

OTHER TIPS

In the C languages there is simply no way to force inlining. inline is just a hint to the compiler to perform inlining, but it is not required to do so.

The only way to "force inline" would be to use preprocessor macros, but that's easy to get wrong. Wrong in that the macro doesn't do what you expect, and wrong in that the macro actually produces slower code. Also, preprocessor macros are no substitute for member functions.

So, if the compiler doesn't want to inline, there's not much you can do about it, and nothing you should do about it.

The answer by Timo is correct for any combination of the /EH?? flag (and /EH?? must be specified to allow any useful exception handling), specifically, MSVC Studio-2015 as well as Studio-2017 15.1 and 15.2 versions will not ever inline a function call if a D'tor is present.

However, I recently found a UserVoice Issue -- Support inlining for functions returning unwindable objects -- for this: (Dec', 2016)

Within deeply-templated codes, it seems quite common to call a function which simply forwards the arguments into another function, which again just forwards the arguments into another function, which again just do forwarding, and so on. As I know, current version of Visual C++ is not able to inline such a function if it returns an object with non-trivial destructor, whenever exceptions are enabled. This often makes a performance hit particularly when the level of forwarding is unavoidably deep and there are many arguments with not-so-small sizes. I very much hoped if the upcoming Visual C++ 2017 has solved this problem, but it seems not.

And a comment that states it will be fixed in VS2017 v15 .3 and links to a connect issue where a comment states:

The inlining limitation was because of the presence of exception handling. We have recently improved our inliner and it can now inline std::make_unique in the case you provided. Please download the latest VS 2017 version to try it out. Note that in VS 2017 RTM, this new inlining is off by default, but you can turn it on by adding the flags /d1ReturnUdtEHInline /d2ReturnUdtEHInline to cl.exe. It will be on by default in a future release.

Note that /d1 and /d2 switches are undocumented switches for the front/backend of the compiler.

and

You should expect it to be on by default in the VS 2017 15.3 release.

So, maybe there's hope this will be actually fixed in VS2017 U3.


Two short Godbolt examples to experiment with:

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top