Syntax of new functions in C ++

I am a programmer who learned C ++ while going through changes and avoiding STL. Instead, I used the MFC container classes and all container classes were available with the framework being used.

I also never used smart pointers. 8)

So I am considering new features in C ++ (as of VS 2013)

The following compiles and works great:

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;
}

      

You can't:

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)
{

}

      

The following error message appears:

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>          ]

      

So, I tried the standard iterators:

for (auto thing = things.begin(); thing != things.end(); ++thing)
{
    cout << "Name: " << (*thing)->getName() << " age: " << (*thing)->getAge() << endl;
}

      

which compiles fine, so why doesn't the for (auto thing: things) syntax work?

Here's my definition for 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;
};

      

and the code:

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)
{
}

      

I added a default constructor and a copy constructor, but still get the function removed.

+3


source to share


4 answers


auto thing : things

copies by value, which is disabled for unique_ptr

. Use instead:

auto &thing : things

      



The difference between this case and an iterator based loop is what is auto thing

defined in this case according to auto thing = *begin;

( see here for more information).

However, when you write auto thing = things.begin();

, thing

in fact, an iterator, so everything is in order.

+8


source


auto thing : things

means that the value thing

at each iteration is a copy of the item things

. If the type is not copied (as it is unique_ptr

not), this will not work.

Make a thing

link instead :



for (auto & thing : things)   // add "const" if appropriate

      

+7


source


In some cases (for example, if things

it turns out vector<bool>

) for (auto& thing : things)

it will not compile. A more general approach is to use

for (auto&& thing : things)

      

This is the syntax that C ++ 17 will implicitly use for loop-based ( for (thing : things)

) ranges , so you might start getting used to it right now.

+2


source


In addition to using

for (auto & thing : things)

      

to access your objects instead of a copy, consider this:

things.push_back(unique_ptr<Thing>(new Thing("tom", 23)));

      

This creates a new chunk Thing

on the heap and pushes the vector pointer over it things

. Why not just save Thing

in things

and let the vector handle all the memory for you?

things.push_back(Thing("tom", 23);

      

+1


source







All Articles