尝试添加带有附加智能指针的矢量

Trying to Add Vectors with Attached Smart Pointers

提问人:Michael Sipos 提问时间:11/9/2023 最后编辑:wohlstadMichael Sipos 更新时间:11/9/2023 访问量:105

问:

我正在尝试通过使用智能指针来处理内存管理来提高我的编码技能,并创建了一个简单的程序来添加两个 2D 矢量结构的组件并将其保存到第三个 2D 矢量结构中。

当我调用该函数时,编译器正在爆炸。addVec2()

实际将智能指针(指向实际数据结构而不是基元)传递给函数的例子并不多。

有人可以帮忙解决这个问题吗?

谢谢。

#include <iostream>
#include <memory>
#include <vector>

#define ENDL "\n"


struct vec2
{
    int a;
    int b;
};


template<typename T>
void addVec2(T *v1, T *v2, T *v3)
{
    v3->a = v1->a + v2->a;
    v3->b = v1->b + v2->b;
}


int main() {

    std::unique_ptr<vec2> p_vec1(new vec2);
    p_vec1->a = 1;
    p_vec1->b = 2;

    std::unique_ptr<vec2> p_vec2(new vec2);
    p_vec2->a = 3;
    p_vec2->b = 7;

    std::unique_ptr<vec2> p_vec3(new vec2);


    addVec2<std::unique_ptr<vec2>>(p_vec1, p_vec2, p_vec3);

    return 0;
}


我什至尝试使用模板来尝试解决它抱怨只能将类型输入函数而不是仍然指向相同类型()的任何类型的指针的问题,但这仍然不起作用。unique_ptrvec2

C++ 智能指针

评论

1赞 wohlstad 11/9/2023
std::unique_ptr不可复制,因此不能按值将其传递给 。但在这种情况下,你根本不需要智能指针 - 只需在堆栈上声明对象并提出接受参数即可。addVec2vec2addVec2T&
7赞 Some programmer dude 11/9/2023
我的建议是,不要将智能指针仅仅视为一种自删除指针,而应将其视为所有权。考虑到这一点,你真的需要这里的指针吗?虽然它可能只适合简单的练习,但你展示的示例根本不需要指针,你可以直接将普通对象与引用一起使用。
0赞 Some programmer dude 11/9/2023
至于调用,编译器可以从参数中推断出模板类型,因此只需要。addVec2<std::unique_ptr<vec2>>(p_vec1, p_vec2, p_vec3)addVec2(p_vec1, p_vec2, p_vec3)
0赞 Michael Sipos 11/9/2023
感谢大家的支持!虽然这个例子对于智能指针之类的东西来说有点太简单了,但我想学习如何为更复杂的对象提供更好的内存管理,并弄清楚如何在不让编译器惊慌失措的情况下通过函数传递它们。智能指针的概念及其正确用法对我来说是新的,所以我试图找出一些概念验证测试。
0赞 Red.Wave 11/9/2023
第一个问题:不必要地使用原始指针而不是引用:.第二个问题:不必要的显式模板参数错误。第三个问题:错误地使用原始指针代替原始指针;需要访问器。第四个问题:必须更换。vec2 operator+(vec2 const&, vect2 const&);<unique_ptr<T>>unique_ptrget()std::make_uniquenew

答:

0赞 wohlstad 11/9/2023 #1

问题:
按值接受参数。但是不可复制的,因此您不能按值传递它们。
addVec2std::unique_ptr

我不建议立即解决的办法可能是通过引用(输入的常量引用)接受参数:

template<typename T>
//-------------vvvvvvv-------vvvvvvv-------v----
void addVec2(T const & v1, T const & v2, T & v3)
{
    v3->a = v1->a + v2->a;
    v3->b = v1->b + v2->b;   
}

但在这种情况下,您实际上并不需要智能指针。
您可以在堆栈上声明对象,并在以下代码中通过引用接受它们:
vec2addVec2

struct vec2
{
    int a;
    int b;
};

template<typename T>
void addVec2(T const & v1, T const & v2, T & v3)
{
    v3.a = v1.a + v2.a;
    v3.b = v1.b + v2.b;
}

int main() {

    vec2 v1{ 1, 2 };
    vec2 v2{ 3, 7 };
    vec2 v3;
    addVec2(v1, v2, v3);
}

请注意,当我调用时,我没有指定模板参数类型 - 编译可以从参数中推断出来。addVec2

0赞 Some programmer dude 11/9/2023 #2

问题似乎是你混淆了智能指针和普通的非拥有非智能指针......

作为参数,编译器和函数需要指向对象的指针T* v1std::unique_ptr<vec2>

所以你的电话真的应该是.在函数内部,您需要使用例如,等。addVec2(&p_vec1, &p_vec2, &p_vec3)(*v1)->a

或者将函数参数更新为引用而不是指针。

评论

0赞 Michael Sipos 11/9/2023
感谢您的见解,以及许多其他人所说的内容消除了这种担忧,因为我开始认为每个函数只能专门处理一种类型的指针。
0赞 Dong 11/9/2023 #3

std::unique_ptr 无法复制。 因此,您可以使用 std::shared_ptr 而不是 std::unique_ptr

template<typename T>
void addVec2(T &v1, T &v2, T &v3)
{
    v3->a = v1->a + v2->a;
    v3->b = v1->b + v2->b;
}
3赞 Peng Guanwen 11/9/2023 #4

你正在传递给 ,但它不是 .只需将参数从指针更改为引用即可解决问题。std::unique_ptraddVec2T*addVec2

template<typename T>
void addVec2(T &v1, T &v2, T &v3)
{
    v3->a = v1->a + v2->a;
    v3->b = v1->b + v2->b;
}

int main() {
    // ...
    addVec2<std::unique_ptr<vec2>>(p_vec1, p_vec2, p_vec3);
}

但我建议你通过一个,而不是.所以最好写:vec2&std::unique_ptr<vec2>&

template<typename T>
void addVec2(const T &v1, const T &v2, T &v3)
{
    v3.a = v1.a + v2.a;
    v3.b = v1.b + v2.b;
}

int main() {
    // ...
    addVec2(*p_vec1, *p_vec2, *p_vec3);
}

请注意,addVec2 的 type 参数可以推导。并且被添加到和,因为我们不修改它们。constv1v2

0赞 Michael Sipos 11/9/2023 #5

我不得不四处挖掘,但发现这个教程网站非常有用,它回答了我的问题,足以让我得到一个可用的解决方案,尽管我不知道这是否是“正确”的做事方式。

https://www.learncpp.com/cpp-tutorial/stdunique_ptr/

#include <iostream>
#include <memory>
#include <vector>

#define ENDL "\n"


struct vec2
{
    int a;
    int b;
};


void addVec2( vec2 *v1, vec2 *v2, vec2 *v3)
{
    v3->a = v1->a + v2->a;
    v3->b = v1->b + v2->b;
}


int main() {

    auto ptr1{ std::make_unique<vec2>() };
    ptr1->a = 1;
    ptr1->b = 2;

    auto ptr2{ std::make_unique<vec2>() };
    ptr2->a = 3;
    ptr2->b = 7;

    auto ptr3{ std::make_unique<vec2>() };


    addVec2(ptr1.get(), ptr2.get(), ptr3.get());

    std::cout << ptr3->a << "," << ptr3->b << ENDL;

    return 0;
}

评论

1赞 wohlstad 11/9/2023
虽然它可以工作,但它并不是解决这个问题的最佳方法。有关更多详细信息,请参阅我的回答。
0赞 Michael Sipos 11/9/2023
@wohlstad好的,谢谢!