gpt4 book ai didi

c++ - 如何使用std::vector >作为默认参数

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:10:14 24 4
gpt4 key购买 nike

编辑2:
澄清:
这个问题源于一个问题,该问题实际上与默认参数本身无关,但与复制构造函数和移动构造函数无关。
我接受了实际上可以回答问题的答案(因此,如果您因为问题标题而在这里,请阅读它),并会解释为什么最初对我不起作用。
怎么了
因此,如“EDIT:”中所述的问题实际上非常简单:
对包含std::vector<std::unique_ptr<T>>的类的分配将中断VisualStudio 2013中的编译(未经其他版本测试),并且错误消息非常隐晦。
评论中的假设是VC编译器存在一个错误,并试图调用一个不存在的拷贝构造函数。
该死,现在怎么办?
这个假设实际上是正确的,但在我最初理解的意义上并不是这样。
实际上,VCC实际上确实尝试调用隐式定义的MyClass的move构造函数。但是,这就是问题所在,它没有正确定义它:
当明确定义移动构造函数MyClass(MyClass && a)时,我们实际上可以通过编写如下代码来模仿编译器的行为:

MyClass(MyClass && a)
: foos_(a.foos_)
{}
使用此代码会生成与使用隐式定义完全相同的错误消息,我想
您可以立即在这里看到问题所在:此move构造函数实际上尝试调用 foos_的拷贝构造函数,这当然是不可能的,因为它又不能为其内容调用拷贝构造函数,因为它们的类型为 std::unique_ptr由于明显的原因,它没有复制构造函数。
当改用这段代码时,
MyClass(MyClass && a)
: foos_(std::move(a.foos_))
{}
一切工作都很好,因为现在调用了 std::vector的move构造函数,从而调用了其内容的move构造函数。
那么谁该怪?
可能性1:
实际上,这是一个编译器错误,起源于模板解决问题。
编译器希望在需要时隐式定义一个移动构造函数,并且如果类定义中存在不可复制的类型,并且代码中曾经对该类进行过分配,则编译器也会这样做。
如果满足这两个条件,它将继续定义move-constructor,但现在似乎并不关心 std::vector模板的实际类型,而只关心类本身,而该类本身确实定义了一个拷贝 constructor, so the VCC tries to use it, which fails because of the missing copy constructor in std::unique_ptr `。
或者,它只是完全跳过了移动构造函数的定义,并尝试使用复制构造函数,这会导致相同的错误。
可能性2:
Microsoft STL实现中有些麻烦。这只是一个线索,我无法解释它是如何工作的,但是对我来说似乎是一种可能性。
如何避免这种困惑?
轻松定义您自己的move构造函数,如上所示。

编辑:
似乎归结为一个特定的问题,原始答案发布在下面。
在Visual Studio(2013)中,创建一个全新的Win32控制台应用程序,不要更改任何设置并将其设置为主 .cpp:
// ConsoleApplication2.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <vector>
#include <memory>

class Foo { };

class MyClass
{
public:
MyClass(std::vector<std::unique_ptr<Foo>> foos) :
foos_(std::move(foos))
{};

std::vector<std::unique_ptr<Foo>> foos_;
};

int _tmain(int argc, _TCHAR* argv[])
{
auto test = MyClass(std::vector<std::unique_ptr<Foo>>()); //remove this, and all works fine!
return 0;
}
尝试对其进行编译将导致以下错误(肯定适用于gcc!):
1>  ConsoleApplication2.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<Foo,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
1> with
1> [
1> _Ty=Foo
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Foo,std::default_delete<_Ty>>::unique_ptr'
1> with
1> [
1> _Ty=Foo
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1> with
1> [
1> _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<Foo,std::default_delete<Foo>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::unique_ptr<Foo,std::default_delete<Foo>>>
1> ]
1> c:\users\felix\source\repos\infinite whitewursht\infinitewhitewursht\consoleapplication2\consoleapplication2.cpp(18) : see reference to class template instantiation 'std::vector<std::unique_ptr<Foo,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=Foo
1> ]

假设我有一个像这样的构造函数:
MyClass(vector<unique_ptr<Foo>> foos) :
foos_(std::move(foos))
{};
通过这种简单的设置,一切都可以正常编译。
MyClass(vector<unique_ptr<Foo>>);这样的构造函数的调用成功,并且行为符合预期。但我想将 foos作为默认参数。
如何获得 foos的默认值?
这是我想出的:
MyClass(vector<unique_ptr<Foo>> foos = vector<unique_ptr<Foo>>()) :
foos_(std::move(foos))
{};
但不幸的是,这不起作用。我不知道为什么,如果有人可以对此有所阐明,那将是很好的。
接下来的两次尝试是解决方法,而不是实际的默认参数:
MyClass() :
foos_() //or foos_(vector<unique_ptr<Foo>>())
{};
也不要工作。这两种方法都会导致来自编译器的错误消息和冗长的输出,其中最有趣的部分是:

c:\users\ username \source\repos\myProject\myProject\MyClass.h(47) : see reference to class template instantiation


其中47是 MyClass中实际 vector 定义的行号:
vector<unique_ptr<GameObject>> foos_;
因此,我的猜测是这确实与我在初始化中犯了一个严重错误有关。
另外,我正在VS2013上进行编译。
整个错误:
GameObject.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(593): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' : attempting to reference a deleted function
1> with
1> [
1> _Ty=int
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
1> with
1> [
1> _Ty=int
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(592) : while compiling class template member function 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)'
1> with
1> [
1> _Ty=std::unique_ptr<int,std::default_delete<int>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0(723) : see reference to function template instantiation 'void std::allocator<_Ty>::construct(_Ty *,const _Ty &)' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int,std::default_delete<int>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits(572) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int,std::default_delete<int>>
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector(650) : see reference to class template instantiation 'std::is_empty<_Alloc>' being compiled
1> with
1> [
1> _Alloc=std::allocator<std::unique_ptr<int,std::default_delete<int>>>
1> ]
1> c:\users\felix\source\repos\infinite whitewursht\infinitewhitewursht\infinitewhitewursht\gameobject.h(47) : see reference to class template instantiation 'std::vector<std::unique_ptr<int,std::default_delete<_Ty>>,std::allocator<std::unique_ptr<_Ty,std::default_delete<_Ty>>>>' being compiled
1> with
1> [
1> _Ty=int
1> ]

最佳答案

编写构造函数重载,它根本不需要 vector ,并且默认情况下会初始化 vector (为空 vector ):

MyClass() : foos_{}
{}

关于c++ - 如何使用std::vector <unique_ptr <T >>作为默认参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23281405/

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