Smart Pointers (shared_ptr and ComPtr)

Started by
28 comments, last by Happy SDE 7 years ago

How many D3D objects do you have? (how much bytes are you going to save?)

It feels not like solving a performance issue, but rather a design issue. Since all the pointers are not allowed to be nullptr, which can only be enforced with a reference. Using a ComPtr or SharedPtr seems the wrong tool if the ref count stays one. But because I do not find online examples/tutorials pursuing a similar philosophy, I start wondering whether I missed pitfalls. Move semantics is problematic, but then you could use reference_wrapper.

🧙

Advertisement

It feels not like solving a performance issue, but rather a design issue. Since all the pointers are not allowed to be nullptr, which can only be enforced with a referenc

Is it better to throw when you try to create an object (texture for example), but failed?

That will solve a problem of having nullptr instead of fully constructed object.

It feels not like solving a performance issue, but rather a design issue. Since all the pointers are not allowed to be nullptr, which can only be enforced with a referenc

Is it better to throw when you try to create an object (texture for example), but failed?

That will solve a problem of having nullptr instead of fully constructed object.

Creating a reference to nullptr will throw something (or just error?), but you could throw something yourself before making a reference and this is only one location in code (as opposed to all the methods excepting a pointer).

🧙

Creating a reference to nullptr will throw something (or just error?), but you could throw something yourself before making a reference and this is only one location in code (as opposed to all the methods excepting a pointer).

void __cdecl main()
{
    int* pi = nullptr;        //Construction
    std::cout << *pi << '\n'; //Usage
}

In my case there will exception in construction.

In your case there will be "access violation" exception in usage.

I would prefer the first one.

In my case there will exception in construction. In your case there will be "access violation" exception in usage. I would prefer the first one.

Interesting. But does a reference would ever make sense for you?

🧙

But does a reference would ever make sense for you?

Expensive copy construction avoidance :wink:

But does a reference would ever make sense for you?

Big object copy construction avoidance :wink:

For C++11 not really an issue anymore with the move semantics. But here you could use the pointer as well?

I would reformulate and nuance my previous question: Does a pointer to reference conversion would ever make sense for you?

🧙

For C++11 not really an issue anymore with the move semantics.

[I've updated my answer before you posted this message], so not "Big", but "Expensive".

If you pass std::string by value to a function, there will be "new" + copy. Move will not work here.

If you pass ComPtr<> by value, there will be AddRef/Release().

Does a pointer to reference conversion would ever make sense for you?

Nothing comes to my mind right now.

Let's take a look at the problem from a different angle:

Input:

1. You have COM object (by D3D), for example, texture.

2. You have wrapper - WRL::ComPtr<>, that stores a pointer (you can't do better with your code, because you need to store a pointer).

3. Reference counting is baked inside the texture, and not inside the wrapper (ComPtr).

std::shared_ptr<> will add 2 counters: ref + weak_ref.

4. COM is a C API (dll-bounary restriction)

5. Amount of D3D object usage inside a renderer is 1.000-50.000 (take a look by Alt+F5 in VS with your program).

Output:

1. What is it possible to improve here on CPU side?

2. Does it worth to improve it?

3. Reference counting is baked inside the texture, and not inside the wrapper (ComPtr).

:O Didn't know, thought it was similar to shared_ptr except for the destructor.

class PassA { PassA(IL* il) : m_il{il}{} IL* m_il; } class PassB { PassB(IL* il) : m_il{il}{} IL* m_il; }

I still wonder why you pass a raw pointer if PassA and PassB are going to have the pointer as member?


🧙

matt77hias, on 27 Mar 2017 - 10:30 PM, said: class PassA { PassA(IL* il) : m_il{il}{} IL* m_il; } class PassB { PassB(IL* il) : m_il{il}{} IL* m_il; } I still wonder why you pass a raw pointer if PassA and PassB are going to have the pointer as member?

1. Real owner - is SharedObjects object.

2. It will outlive PassA && PassB => no need them to be owners.

3. For usage, D3D requires from you IL raw pointer, not ComPtr => You will need to call ComPtr<>::Get() in Render() or just store it as raw pointer.

This topic is closed to new replies.

Advertisement