I am reading about the new C++11 syntax for iterating over STL containers.
So far I came across the following example:
std::vector<int> plus;
....
for(int l : plus)
{
std::cout << l;
}
My question is does the above syntax make a copy of the int ?
If so wouldnt this be more efficient ?:
for(int& l : plus)
Semantically, it makes a copy, although for built-in types there may be no efficiency hit, in fact it may even be cheaper to use a copy. But if you have expensive to copy objects, it is a better idea to use const references in the loop.
std::vector<ExpensiveToCopy> v;
for (const auto& i : v)
std::cout << i << std::endl;
You should only really use non-const references if you want to mutate the object.
Yes, if you don't explicitly say you want a reference, you get a copy. With built-in types, its actually more efficient to take a copy - unless you want the semantics of references, of course.
It will call the copy constructor for each element in the vector. If you take it by const reference, it doesn't call any constructors at all. You should use const if you don't plan on mutating the elements. For example:
class Test
{
public:
Test() { std::cout << "Default.\n"; }
~Test() { }
Test(const Test& other) { std::cout << "Copy.\n"; }
Test(Test&& other) { std::cout << "Move.\n"; }
};
int main()
{
std::vector<Test> test;
test.emplace_back(Test());
for (const Test& t : test)
{
}
}
Related
I am learning to use C++ vectors, and I can't quite understand the output of the following program:
#include <iostream>
#include <vector>
using namespace std;
class Custom {
public:
int v;
Custom() = delete;
explicit Custom(int v) : v{v} {};
Custom(const Custom &) : v{4} {
}
friend ostream &operator<<(ostream &os, const Custom &th) {
os << "V is " << th.v << endl;
return os;
}
};
int main(int argc, char *argv[]) {
vector<Custom> c(2, Custom(3));
c[0].v = 5;
for (auto i: c) {
cout << i << endl;
}
}
I expected it to produce the output
V is 5
V is 4
But instead it produces
V is 4
V is 4
Am I missing something obvious? Thanks.
This range based loop is making copies:
for (auto i: c) {
cout << i << endl;
}
And the copy constructor initializes v to 4 (and does not make a copy):
Custom(const Custom &) : v{4} {
}
You can either implement a proper copy constructor or use references in the loop to get the desired output:
for (const auto& i: c) {
cout << i << endl;
}
I would suggest to do both, because this copy constructor is not doing a copy by any means. The compiler generated copy constructor should be fine:
Custom(const Custom &) = default;
PS: The fact that Custom has a deleted default constructor is not really relevant for the posted code. Nowhere in the code a Custom is default constructed. Also there is no iterator in your code. In the range based loop i is a copy/reference of the elements in the vector, it is not an iterator.
When you wrote:
for (auto i: c) //this uses copy constructor to copy initialize each element one by one from the vector
{
}
In the above snippet, each individual element of the vector is used to copy initiaize a temporary object named i while iterating through the vector. And since you have the v{4} in the constructor initializer list of the copy constructor you get the mentioned output.
To solve this you should replace: auto i: c with auto &i: c or const auto &i: c as shown below:
for (const auto &i: c)
{
cout << i << endl;
}
Now the elements of the vector are not copied into i. Instead they are references to the object themselves and so you'll get your expected output.
I'm trying to write a class that contains a function returning one of the class members, and I want to allow the caller to either move or copy the returned value. I wrote some dummy structs to test this; and after trying different variations, this seems to give me what I want.
#include <iostream>
using namespace std;
struct S {
int x;
S() : x(10) { cout << "ctor called\n"; }
S(const S& s) : x(s.x) { cout << "copy ctor called\n"; }
S(S&& s) : x(s.x) { cout << "move ctor called\n"; }
// I'm implementing move and copy the same way since x is an int.
// I just want to know which one gets called.
};
struct T {
S s;
T() : s() {}
S&& Test() && {
return move(s);
}
const S& Test() & {
return s;
}
};
int main() {
T t;
auto v = move(t).Test();
cout << v.x << "\n";
T t2;
auto w = t2.Test();
cout << w.x << "\n";
return 0;
}
The code prints out (with clang++-5.0 c++14):
ctor called
move ctor called
10
ctor called
copy ctor called
10
Is this an acceptable way to implement what I want? I have a few questions:
In the first Test function, I tried both S&& and S for the return type and it doesn't change the output. Does && mean anything for the (non-template) returned type?
Is it guaranteed that auto v = move(t).Test() would only invalidate the "moved" member? If struct T had other member variables, can I assume this call wouldn't invalidate them?
In the first Test function, I tried both S&& and S for the return type and it doesn't change the output. Does && mean anything for the (non-template) returned type?
There are little differences:
S&& is a (r-value) reference, so object is not yet moved.
returning S would move-construct S, so member is moved once the method is called.
For move(t).Test();, return ingS&& does nothing whereas returning S would move the member.
Is it guaranteed that auto v = move(t).Test() would only invalidate the "moved" member? If struct T had other member variables, can I assume this call wouldn't invalidate them?
Yes, only T::s is moved. std::move is just a cast to rvalue.
Yes it is acceptable way to implement this.
It does the same thing because returned value is temporary object, thus rvalue.
Depends on what you mean by invalidating
I realized that the common-knowledge that "you cannot move a const object" is not entirely true. You can, if you declare the move ctor as
X(const X&&);
Full example below:
#include <iostream>
struct X
{
X() = default;
X(const X&&) {std::cout << "const move\n";}
};
int main()
{
const X x{};
X y{std::move(x)};
}
Live on Coliru
Question: is there any reason why one would want such a thing? Any useful/practical scenario?
Your example doesn't move anything. Yes, you wrote std::move to get an rvalue and you invoked a move constructor, but nothing actually ends up getting moved. And it can't, because the object is const.
Unless the members you were interested in were marked mutable, you would not be able to do any "moving". So, there is no useful or even possible scenario.
Not sure whether it's practical, but it can be made legal provided the modified data members are mutable.
This program is legal, and if you like that kind of thing, would easily become hard to follow:
#include <iostream>
#include <string>
struct animal
{
animal(const animal&& other) : type(other.type) {
other.type = "dog";
}
animal() = default;
mutable std::string type = "cat";
};
std::ostream& operator<<(std::ostream& os, const animal& a)
{
return os << "I am a " << a.type;
}
std::ostream& operator<<(std::ostream& os, const animal&& a)
{
return os << "I am a " << a.type << " and I feel moved";
}
int main()
{
const auto cat = animal();
std::cout << cat << std::endl;
auto dog = std::move(cat);
std::cout << cat << std::endl;
std::cout << dog << std::endl;
std::cout << std::move(dog) << std::endl;
}
expected output:
I am a cat
I am a dog
I am a cat
I am a cat and I feel moved
As the comments have noted, you cannot actually "move" anything out of the argument object, because it is const (at least, not without a const cast, which is a bad idea as it could lead to UB). So it's clearly not useful for the sake of moving. The entire purpose of move semantics is to provide a performance optimization, and that is not happening here, so why do it?
That said, I can only think of two cases where this is useful. The first involves "greedy" constructors:
#include <iostream>
struct Foo {
Foo() = default;
Foo(const Foo&) { std::cerr << "copy constructor"; }
Foo(Foo&&) { std::cerr << "copy constructor"; }
template <class T>
Foo(T&&) { std::cerr << "forward"; }
};
const Foo bar() { return Foo{}; }
int main() {
Foo f2(bar());
return 0;
}
This program prints "forward". The reason why is because the deduced type in the template will be const Foo, making it a better match. This also shows up when you have perfect forwarding variadic constructors. Common for proxy objects. Of course returning by const value is bad practice, but strictly speaking it's not incorrect, and this may break your class. So you should really provide a Foo(const Foo&&) overload (which just delegates to the copy constructor); think of it as crossing a t or dotting an i when you are writing high quality generic code.
The second case occurs when you want to explicitly delete move constructors, or a move conversion operator:
struct Baz {
Baz() = default;
Baz(const Baz&) = default;
Baz(Baz&&) = delete;
};
const Baz zwug() { return {}; }
int main() {
Baz b2(zwug());
}
This program compiles so the author failed at their mission. The reason why is because const ref overloads match against const rvalues, and const rvalue construction was not explicitly deleted. If you want to delete moves you'll need to delete the const rvalue overload too.
The second example may seem wildly obscure but say you are writing a class that provides a view of a string. You may not want to allow it to be constructed from a string temporary, since you are at greater risk of the view being corrupted.
I have a complex object that looks something like this:
struct A
{
int a;
}
struct B
{
int b;
vector<A> vecA;
}
I am current printing out a vector of B in the following way:
struct PrintStruct
{
ostream &ostream_;
PrintStruct(ostream &stream) : ostream_(stream) {}
void operator()(const A& elementA)
{
ostream_ << elementA.a;
}
void operator()(const B& elementB)
{
ostream_ << elementB.b;
for_each(elementB.vecA.begin(), elementB.vecA.end(), (*this));
}
}
void print()
{
vector<B> vecB;
for_each(vecB.begin(), vecB.end(), PrintStruct(cout));
}
Is that necessarily the best way to do it? My main point of concern is calling the (*this) in the for_each within the functor itself. Is that safe to do? I think it should be, but I'm not sure if there will be any unintended consequences?
My main point of concern is calling the (*this) in the for_each within the functor itself. Is that safe to do?
It cannot be answered in general but in your case, it is safe.
The call to for_each makes a copy of the PrintStruct object and uses it. The ostream_ member of the copy will be reference the same object as the ostream_ member of the original PrintStruct. There should be no problem with it.
I strongly believe that for_each has mostly outlived itself. I see no benefit in it when compared with range loops. The code actually looks cleaner, more straitghtforward, doesn't require ad-hoc classess or lambdas when used like this:
void print()
{
vector<B> vecB;
for(const auto& elem : vecB) {
std::cout << elem;
}
}
Is there a way to make a non-resizeable vector/array of non-reassignable but mutable members? The closest thing I can imagine is using a vector<T *> const copy constructed from a temporary, but since I know at initialization how many of and exactly what I want, I'd much rather have a block of objects than pointers. Is anything like what is shown below possible with std::vector or some more obscure boost, etc., template?
// Struct making vec<A> that cannot be resized or have contents reassigned.
struct B {
vector<A> va_; // <-- unknown modifiers or different template needed here
vector<A> va2_;
// All vector contents initialized on construction.
Foo(size_t n_foo) : va_(n_foo), va2_(5) { }
// Things I'd like allowed: altering contents, const_iterator and read access.
good_actions(size_t idx, int val) {
va_[idx].set(val);
cout << "vector<A> info - " << " size: " << va_.size() << ", max: "
<< va_.max_size() << ", capacity: " << va_.capacity() << ", empty?: "
<< va_.empty() << endl;
if (!va_.empty()) {
cout << "First (old): " << va_[0].get() << ", resetting ..." << endl;
va_[0].set(0);
}
int max = 0;
for (vector<A>::const_iterator i = va_.begin(); i != va_.end(); ++i) {
int n = i->get();
if (n > max) { max = n; }
if (n < 0) { i->set(0); }
}
cout << "Max : " << max << "." << endl;
}
// Everything here should fail at compile.
bad_actions(size_t idx, int val) {
va_[0] = va2_[0];
va_.at(1) = va2_.at(3);
va_.swap(va2_);
va_.erase(va_.begin());
va_.insert(va_.end(), va2_[0]);
va_.resize(1);
va_.clear();
// also: assign, reserve, push, pop, ..
}
};
There is an issue with your requirements. But first let's tackle the fixed size issue, it's called std::tr1::array<class T, size_t N> (if you know the size at compile time).
If you don't know it at compile time, you can still use some proxy class over a vector.
template <class T>
class MyVector
{
public:
explicit MyVector(size_t const n, T const& t = T()): mVector(n,t) {}
// Declare the methods you want here
// and just forward to mVector most of the time ;)
private:
std::vector<T> mVector;
};
However, what is the point of not being assignable if you are mutable ? There is nothing preventing the user to do the heavy work:
class Type
{
public:
int a() const { return a; }
void a(int i) { a = i; }
int b() const { return b; }
void b(int i) { b = i; }
private:
Type& operator=(Type const&);
int a, b;
};
Nothing prevents me from doing:
void assign(Type& lhs, Type const& rhs)
{
lhs.a(rhs.a());
lhs.b(rhs.b());
}
I just want to hit you on the head for complicating my life...
Perhaps could you describe more precisely what you want to do, do you wish to restrict the subset of possible operations on your class (some variables should not be possible to modify, but other could) ?
In this case, you could once again use a Proxy class
class Proxy
{
public:
// WARN: syntax is screwed, but `vector` requires a model
// of the Assignable concept so this operation NEED be defined...
Proxy& operator=(Proxy const& rhs)
{
mType.a = rhs.mType.a;
// mType.b is unchanged
return *this;
}
int a() const { return mType.a(); }
void a(int i) { mType.a(i); }
int b() const { return mType.b(); }
private:
Type mType;
};
There is not much you cannot do with suitable proxies. That's perhaps the most useful pattern I have ever seen.
What you're asking is not really possible.
The only way to prevent something from being assigned is to define the operator = for that type as private. (As an extension of this, since const operator = methods don't make much sense (and are thus uncommon) you can come close to this by only allowing access to const references from your container. But the user can still define a const operator =, and you want mutable objects anyways.)
If you think about it, std::vector::operator [] returns a reference to the value it contains. Using the assignment operator will call operator = for the value. std::vector is completely bypassed here (except for the operator[] call used to get the reference in the first place) so there is no possibility for it (std::vector) to in any way to override the call to the operator = function.
Anything you do to directly access the members of an object in the container is going to have to return a reference to the object, which can then be used to call the object's operator =. So, there is no way a container can prevent objects inside of it from being assigned unless the container implements a proxy for the objects it contains which has a private assignment operator that does nothing and forwards other calls to the "real" object, but does not allow direct access to the real object (though if it made sense to do so, you could return copies of the real object).
Could you create a class which holds a reference to your object, but its constructors are only accessible to its std::vector's friend?
e.g.:
template<typename T>
class MyRef {
firend class std::vector< MyRef<T> >
public:
T& operator->();
[...etc...]
You can achieve what you want by making the std::vector const, and the vector's struct or class data mutable. Your set method would have to be const. Here's an example that works as expected with g++:
#include <vector>
class foo
{
public:
foo () : n_ () {}
void set(int n) const { n_ = n; }
private:
mutable int n_;
};
int main()
{
std::vector<foo> const a(3); // Notice the "const".
std::vector<foo> b(1);
// Executes!
a[0].set(1);
// Failes to compile!
a.swap(b);
}
That way you can't alter the vector in any way but you can modify the mutable data members of the objects held by the vector. Here's how this example compiles:
g++ foo.cpp
foo.cpp: In function 'int main()':
foo.cpp:24: error: passing 'const std::vector<foo, std::allocator<foo> >' as 'this' argument of 'void std::vector<_Tp, _Alloc>::swap(std::vector<_Tp, _Alloc>&) [with _Tp = foo, _Alloc = std::allocator<foo>]' discards qualifiers
The one disadvantage I can think of is that you'll have to be more aware of the const-correctness of your code, but that's not necessarily a disadvantage either.
HTH!
EDIT / Clarification: The goal of this approach is not defeat const completely. Rather, the goal is to demonstrate a means of achieving the requirements set forth in the OP's question using standard C++ and the STL. It is not the ideal solution since it exposes a const method that allows alteration of the internal state visible to the user. Certainly that is a problem with this approach.