gpt4 book ai didi

c++ - 需要使用 shared_ptr 吗?

转载 作者:行者123 更新时间:2023-11-27 23:39:39 26 4
gpt4 key购买 nike

我有两个类:Lattice 和 ModelGUI。我想将函数作为回调从 Lattice 传递到 GUI。我将 Lattice 实现为 unique_ptr。一些代码:

模型图形用户界面.h:

using CheckTypeClbk = std::function<Enums::AgentType(int)>;
ModelGUI(const Matrix* matrix_, CheckTypeClbk callback, float windowHeight_, float windowWidth_, float latticeWidth_);

主要.cpp:

std::unique_ptr<ILattice> lattice(new Lattice(5, qMap));
ModelGUI gui(lattice->getLattice(), std::bind(&ILattice::checkAgentType, lattice, std::placeholders::_1),
800, 1200, 800);

通过这个实现,我得到了关于模板的奇怪的编译错误:

1>main.cpp
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\xutility(390): error C2664: 'std::tuple<std::unique_ptr<ILattice,std::default_delete<_Ty>>,std::_Ph<1>>::tuple(std::tuple<std::unique_ptr<_Ty,std::default_delete<_Ty>>,std::_Ph<1>> &&)': cannot convert argument 1 from 'std::unique_ptr<ILattice,std::default_delete<_Ty>>' to 'std::allocator_arg_t'
1> with
1> [
1> _Ty=ILattice
1> ]
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\xutility(389): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\functional(1902): note: see reference to function template instantiation 'std::_Compressed_pair<Enums::AgentType (__cdecl ILattice::* )(int),std::tuple<std::unique_ptr<ILattice,std::default_delete<_Ty>>,std::_Ph<1>>,false>::_Compressed_pair<Enums::AgentType(__cdecl ILattice::* )(int),_Cv_TiD&,const std::_Ph<1>&>(std::_One_then_variadic_args_t,_Other1 &&,_Cv_TiD &,const std::_Ph<1> &)' being compiled
1> with
1> [
1> _Ty=ILattice,
1> _Cv_TiD=std::unique_ptr<ILattice,std::default_delete<ILattice>>,
1> _Other1=Enums::AgentType (__cdecl ILattice::* )(int)
1> ]
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\functional(1903): note: see reference to function template instantiation 'std::_Compressed_pair<Enums::AgentType (__cdecl ILattice::* )(int),std::tuple<std::unique_ptr<ILattice,std::default_delete<_Ty>>,std::_Ph<1>>,false>::_Compressed_pair<Enums::AgentType(__cdecl ILattice::* )(int),_Cv_TiD&,const std::_Ph<1>&>(std::_One_then_variadic_args_t,_Other1 &&,_Cv_TiD &,const std::_Ph<1> &)' being compiled
1> with
1> [
1> _Ty=ILattice,
1> _Cv_TiD=std::unique_ptr<ILattice,std::default_delete<ILattice>>,
1> _Other1=Enums::AgentType (__cdecl ILattice::* )(int)
1> ]
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\functional(1902): note: while compiling class template member function 'std::_Binder<std::_Unforced,Enums::AgentType (__cdecl ILattice::* )(int),std::unique_ptr<ILattice,std::default_delete<_Ty>> &,const std::_Ph<1> &>::_Binder(_Fx &&,std::unique_ptr<_Ty,std::default_delete<_Ty>> &,const std::_Ph<1> &)'
1> with
1> [
1> _Ty=ILattice,
1> _Fx=Enums::AgentType (__cdecl ILattice::* )(int)
1> ]
1>d:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.14.26428\include\functional(1929): note: see reference to function template instantiation 'std::_Binder<std::_Unforced,Enums::AgentType (__cdecl ILattice::* )(int),std::unique_ptr<ILattice,std::default_delete<_Ty>> &,const std::_Ph<1> &>::_Binder(_Fx &&,std::unique_ptr<_Ty,std::default_delete<_Ty>> &,const std::_Ph<1> &)' being compiled
1> with
1> [
1> _Ty=ILattice,
1> _Fx=Enums::AgentType (__cdecl ILattice::* )(int)
1> ]
1>d:\predator-prey\predator-prey\main.cpp(16): note: see reference to class template instantiation 'std::_Binder<std::_Unforced,Enums::AgentType (__cdecl ILattice::* )(int),std::unique_ptr<ILattice,std::default_delete<_Ty>> &,const std::_Ph<1> &>' being compiled
1> with
1> [
1> _Ty=ILattice
1> ]

但是当我使用 shared_ptr 而不是 unique_ptr 时,一切正常。是一种好的做法吗?我听说要尽可能避免使用 shared_ptr,除非它们是完全必要的。

最佳答案

你需要shared_ptr吗?

没有。至少对于给定的例子不是。

如果 latticegui 被定义在不同的范围,不同的生命周期,并且被到处使用,wowie-zowie,我们可以谈论 shared_ptr.

为什么?

让我们从一个非常简单的示例开始,该示例说明了为什么 unique_ptr 会导致悲伤。

#include <functional>
#include <iostream>

struct test
{
test() = default;
test(const test &)
{
std::cout << "copied" << std::endl;
}
void func(int i)
{
std::cout << i << std::endl;
}
};

int main()
{
test t;
std::function<void(int)> f1 = std::bind(&test::func, t, std::placeholders::_1);
f1(1);
}

test 除了告诉我们对象何时被复制并证明函数已运行之外,没有做太多其他事情。执行它我们会看到 t is copied and produced the expected output from the function .

std::unique_ptr 不能被复制,因为这几乎会破坏职位描述的整个 unique 部分。我们看到,如果我们稍微更改 main 以使用 unique_ptr 并更接近所提出的问题。

int main()
{
std::unique_ptr<test> tp = std::make_unique<test>();
std::function<void(int)> f1 = std::bind(&test::func, tp, std::placeholders::_1);
}

As expected, this doesn't compile.我们可以使用 std::reference_wrapper 进行编译

std::function<void(int)> f1 = std::bind(&test::func, std::reference_wrapper<std::unique_ptr<test>>(tp), std::placeholders::_1);

或提供指向bind

的原始指针
std::function<void(int)> f1 = std::bind(&test::func, tp.get(), std::placeholders::_1);    f1(1);

但这需要 tp 具有更广的范围,并保证比 f1 更长寿。这真正归结为为什么首先使用 more than test t;?我们真的需要一个指针吗?

但我们现在就开始吧,因为我们至少可以在我们转向更环保的牧场之前让它看起来更漂亮。这是与 lambda 表达式相同的东西

std::function<void(int)> f1 = [&tp](int i) { tp->func(i); };

通常我不是“Lambda 比 bind 更容易阅读”的拥护者,但这个案例是一个非常有说服力的论据。

回到基础,它与

并没有什么不同
int main()
{
test t;
std::function<void(int)> f1 = [&t](int i) { t.func(i); };
f1(1);
}

并完全消除了指针。没有指针,没有 shared_ptr

如果 t 可以一劳永逸,唯一的用户就是回调,让 lambda 携带 t 的拷贝,让原来的死掉。

std::function<void(int)> scopedemo()
{
test t;
return [t](int i) mutable { t.func(i); }; //
}

int main()
{
auto f1 = scopedemo();
f1(1);

}

注意可变。 Lambda 默认携带常量,不能用于调用非 const 方法或用作非 const 参数。

关于c++ - 需要使用 shared_ptr 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56385863/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com