我是一名程序员,在进行更改并学会避免STL时学习了C ++。相反,我使用了MFC容器类和我可能正在使用的框架可用的任何容器类。
我也从未真正使用智能指针。 8)
所以,我正在研究C ++中的新功能(使用VS 2013)
以下编译并正常工作:
vector<string> names;
names.push_back("tom");
names.push_back("dick");
names.push_back("harry");
names.push_back("bob");
names.push_back("percy");
names.push_back("freddie");
names.push_back("sam");
for (auto name : names)
{
cout << "Name: " << name << endl;
}
以下内容不是:
vector<unique_ptr<Thing>> things;
things.push_back(unique_ptr<Thing>(new Thing("tom", 23)));
things.push_back(unique_ptr<Thing>(new Thing("dick", 26)));
things.push_back(unique_ptr<Thing>(new Thing("harry", 33)));
things.push_back(unique_ptr<Thing>(new Thing("fred", 43)));
things.push_back(unique_ptr<Thing>(new Thing("bob", 53)));
for (auto thing : things)
{
}
我收到以下错误消息:
1>c:\dev\src\samples\consoletest\consoletest\vectorstuff.cpp(34): error C2280: 'std::unique_ptr<Thing,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=Thing
1> ]
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\memory(1486) : see declaration of 'std::unique_ptr<Thing,std::default_delete<_Ty>>::unique_ptr'
1> with
1> [
1> _Ty=Thing
1> ]
所以我尝试了标准迭代器:
for (auto thing = things.begin(); thing != things.end(); ++thing)
{
cout << "Name: " << (*thing)->getName() << " age: " << (*thing)->getAge() << endl;
}
编译好的,为什么for(auto thing:things)语法不起作用?
这是我对Thing的定义:
class Thing
{
public:
Thing();
Thing(const Thing& original);
Thing(const std::string& name, int age);
const std::string& getName() const { return name; }
int getAge() const { return age; }
private:
std::string name;
int age;
};
和代码:
Thing::Thing() : name(""), age(21)
{
}
Thing::Thing(const Thing& original) : name(original.name), age(original.age)
{
}
Thing::Thing(const std::string& name, int age) :
name(name),
age(age)
{
}
我添加了默认构造函数和复制构造函数,但仍然获取了已删除的函数。
答案 0 :(得分:8)
auto thing : things
按值复制,对unique_ptr
禁用。而是使用:
auto &thing : things
这种情况与基于迭代器的循环之间的区别在于,在这种情况下,auto thing
是根据auto thing = *begin;
(see here更多信息)定义的。{/ p >
但是在你编写auto thing = things.begin();
的情况下,thing
实际上是一个迭代器,所以一切都很好。
答案 1 :(得分:7)
auto thing : things
表示每次迭代中thing
的值是things
元素的副本。如果类型不可复制(因为unique_ptr
不是),那么这将不起作用。
相反,请将thing
作为参考:
for (auto & thing : things) // add "const" if appropriate
答案 2 :(得分:2)
在某些情况下(例如,如果things
恰好是vector<bool>
),for (auto& thing : things)
将无法编译。更通用的方法是使用
for (auto&& thing : things)
这是C++17 terse range-based for loops(for (thing : things)
)隐式使用的语法,因此您可以立即开始习惯它。
答案 3 :(得分:1)
除了使用
for (auto & thing : things)
要访问您的对象而不是副本,请考虑以下事项:
things.push_back(unique_ptr<Thing>(new Thing("tom", 23)));
这会在堆上创建一个新的Thing
,并将指向它的指针推送到向量things
中。
为什么不简单地将Thing
存储在things
中并让向量处理所有内存?
things.push_back(Thing("tom", 23);