I'm relatively new to C++ and I'm wondering if structs are copied in the following case:
struct foo {
int i;
std::vector<int> bar;
}
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
void main() {
Foobar foobar;
{
foo f;
f.i = 1;
f.bar.insert(2);
foobar.store(f);
}
// will a copy of f still exist in foobar.m_foo, or am I storing a NULL-Pointer at this point?
}
The reason why I am asking this is that I am originally a .NET developer and in .NET structures will be copied if you pass them to a function (and classes are not).
I'm pretty sure it would be copied if store was not declared to take f by reference, but I cannot change this code.
Edit: Updated the code, because I didn't know that the vector.insert would affect my question. In my case I store the struct as a member in a class, not a vector.
So my question really was: will f be copied at this->m_foo = f;?
Short answer: Yes.
Long answer: You'd have to get a pointer to a stack allocated struct and then let that struct go out of scope in order to end up with a dangling reference in your vector... but even then, you wouldn't have stored a NULL. C and C++ pointers are simple things, and will continue to point at a memory location long after that memory location has become invalid, if your code doesn't overwrite them.
It might also be worth noting that std::vector has a decent set of copy and move functions associated with it that will be called implicitly in this case, so the bar vector inside the struct will also be copied along with the simple integer i. Standard library classes tend to be quite well written, but code by other folk has no such guarantee!
Now, as regards your edit:
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
You will still not have any problems with the foo instance stored in m_foo. This is because this->m_foo = f invokes a copying operation, as m_foo is not a variable of a reference or pointer type. If you had this instead: foo& m_foo then you would run into difficulties because instead of copying a foo instance you are instead copying a reference to a foo instance, and when that instance goes out of scope, the reference is no longer valid.
Yes, the struct will be copied, in the following function:
foos.insert(f);
As a copy is made, you won't be storing a null pointer / null reference.
However, like you've said, it won't be copied when you call store(f); as the function accepts the argument as a reference.
Your edit will still make a copy of Foo. You are assigning one instance of a variable to another instance of a variable. What you aren't doing is assigning one pointer (reference in C#) to another. You could probably do with doing some reading around C++ object instances, pointers, and references.
A copy of f is made during foos.insert(f)
void store(foo& f) {
foos.insert(f);
}
void main() {
{
foo f;
f.i = 1;
f.bar.insert(2);
store(f);
}
// at this place, local variable `f` runs out of scope, it's destroyed and cleaned up
// foos is holding the copy of `f`
}
Related
I have a function that returns an object via a pointer argument. However the object has a private default constructor, so how can I create a variable to pass the address in?
class Foo {
Foo(/*some parameters*/);
private:
Foo();
};
void bar( Foo* foo ) {
*foo = Foo(/*some arguments*/);
}
Foo f; //doesn't compile because default constructor is private
bar( &f );
The code is simplified, I can't really change Foo or bar
Simply use the public, non-default constructor to create the first version of the Foo instance, that will be re-assigned in bar:
Foo f(/*some arguments*/);
bar(&f);
It probably won't matter which argument values you pass, unless the move assignment operator does something special with the old values.
Yes, it seems pointless, but Foo has been designed so that bar is really inconvenient to use (or the other way round).
So there is no way to say just create some space in memory that will fit a Foo, I'll fill it in later?
Not using bar. bar does an assignment, and an assignment requires the left hand side to be an existing object, that is in a valid state.
So why isn't it possible in C++ to create a variable without creating an object?
Why is it in C++ variable and object are so tightly related?
Because that is the way C++ has been specified. A variable is a name for an object. It is not a name for something that might be an object or might be not-an-object. And it's a good decision too. Thanks to this design, you can always rest assured, that the object named by a variable does always exist sans a bug in your program. (Reference variables are different, since they aren't an object themselves).
The issue with Foo and bar isn't a limitation of the language. The issue is bad design of Foo and/or bar.
This doesn't answer the question, because it relies on changing bar, but to answer this comment:
So there is no way to say just create some space in memory that will fit a Foo, I'll fill it in later?
For objects of non-trivial types (like the Foo in your example) the only way to do that is construct a new object at that address, not assign to an existing object. You can do that with a placement new-expression:
void bar( Foo* foo ) {
new (foo) Foo(/*some arguments*/);
}
Now instead of the address of an existing object, the argument to the function needs to be a chunk of uninitialized memory which is suitably-aligned for a Foo object, which you can do with the aligned_storage type:
std::aligned_storage<sizeof(Foo), alignof(Foo)>::type storage;
Foo* addr = reinterpret_cast<Foo*>(&storage);
bar( addr );
However, because you've manually started the lifetime of a Foo at that location, it's also your responsibility to manually end its lifetime, by explicitly invoking the destructor when you're finished with it:
addr->~Foo();
This is obviously more error-prone than relying on the compiler to construct and destroy your object automatically.
I think the person who had written the code for class Foo did not want anyone to create objects of class Foo using default c'tor. Instead he/she wanted to create the objects of class Foo using method bar();
So try this:
class Foo {
Foo(/*some parameters*/);
private:
Foo();
};
void bar( Foo** foo ) {
//*foo = Foo(/*some arguments*/);
*foo = new Foo(/*some arguments*/);
}
Foo *f = NULL; //doesn't compile because default constructor is private
bar( &f );
Note: You need to create a pointer to class Foo i.e *f and pass the address of this pointer. Inside method bar() an object of class Foo will get created and this object's address will be assigned to the pointer f.
I am new to C++11. In fact until recently, I programmed only using dynamic allocation, in a way similar to Java, e.g.
void some_function(A *a){
a->changeInternalState();
}
A *a = new A();
some_function(a);
delete a;
// example 2
some_function( new A() ); // suppose there is **no** memory leak.
Now I want to reproduce similar code with C++11, but without pointers.
I need to be able to pass newly created class class A directly to function useA(). There seems to be a problem if I want to do so with non-const normal reference and It works if I do it with rvalue reference.
Here is the code:
#include <stdio.h>
class A{
public:
void print(){
++p; // e.g. change internal state
printf("%d\n", p);
}
int p;
};
// normal reference
void useA(A & x){
x.print();
}
// rvalue reference
void useA(A && x){
useA(x);
}
int main(int argc, char** argv)
{
useA( A{45} ); // <--- newly created class
A b{20};
useA(b);
return 0;
}
It compiles and executes correctly, but I am not sure, if this is the correct acceptable way to do the work?
Are there some best practices for this kind of operations?
Normally you would not design the code so that a temporary object gets modified. Then you would write your print function as:
void useA(A const & x){
x.print();
}
and declare A::print as const. This binds to both rvalues and lvalues. You can use mutable for class member variables which might change value but without the object logically changing state.
Another plan is to keep just A &, but write:
{ A temp{45}; useA(temp); }
If you really do want to modify a temporary object, you can write the pair of lvalue and rvalue overloads as you have done in your question. I believe this is acceptable practice for that case.
The best thing about C++11 move semantics is that most of the time, you get them "for free" without having to explicitly add any &&s or std::move()s in your code. Usually, you only need to use these things explicitly if you're writing code that does manual memory management, such as the implementation of a smart pointer or a container class, where you would have had to write a custom destructor and copy constructor anyway.
In your example, A is just an int. For ints, a move is no different from a copy, because there's no opportunity for optimization even if the int happens to be a disposable temporary. Just provide a single useA() function that takes an ordinary reference. It'll have the same behavior.
it is stated on this website: http://www.tutorialspoint.com/cplusplus/cpp_variable_scope.htm
Variables that are declared inside a function or block are local
variables. They can be used only by statements that are inside that
function or block of code. Local variables are not known to functions
outside their own.
Then, in the following example;
class foo {
/*....*/
};
foo bar(){
foo f;
return f;
}
void main(){
foo fooReturn = bar();
}
how come when bar() returns, fooReturn contains a valid object? is:
foo f similar to foo *f = new foo(); are both objects on the heap?
thanks
daniel
No, foo f; is very different from foo * f = new foo();, since the former foo is built on the stack, its destructor is automatically called when it goes out of scope, etc.
Instead, the latter foo is built on the heap, requires manual destruction calling delete, etc.
But, in your sample code, the returned foo f is copied or moved (if foo provides move semantics, e.g. move constructor), out of the function bar(). So you have a valid object returned to the caller.
Note
The be more precise, there is an optimization that the C++ compiler may apply, i.e. the RVO (Return Value Optimization), that could avoid the copy or move of the returned foo.
how come when bar() returns, fooReturn contains a valid object?
Because the value of the return expression (f) is used to initialise fooReturn before it's destroyed. As long as the type has correct copy/move semantics, or the copy/move is elided, the resulting object will be valid.
is: foo f similar to foo *f = new foo(); are both objects on the heap?
No, the first is an automatic variable, stored in the function's stack frame and destroyed when it goes out of scope. The second is a dynamic object, stored on the heap, and not destroyed without an explicit delete.
When you return a local object from a function, a copy is created (with a copy costructor). In your example, fooReturn contains a copy of the f object (local to bar). After the f is copied, it is freed.
Although it took me a while to get used to it, I now grew the habit of letting my functions take shared pointer parameters by lvalue-reference to const rather than by value (unless I need to modify the original arguments, of course, in which case I take them by lvalue-reference to non-const):
void foo(std::shared_ptr<widget> const& pWidget)
// ^^^^^^
{
// work with pWidget...
}
This has the advantage of avoiding an unnecessary copy of a shared pointer, which would mean thread-safely increasing the reference counting and potentially incurring in undesired overhead.
Now I've been wondering whether it is sane to adopt a somewhat symmetrical habit for retrieving shared pointers that are returned by value from functions, like at the end of the following code snippet:
struct X
{
// ...
std::shared_ptr<Widget> bar() const
{
// ...
return pWidget;
}
// ...
std::shared_ptr<Widget> pWidget;
};
// ...
// X x;
std::share_ptr<Widget> const& pWidget = x.bar();
// ^^^^^^
Are there any pitfalls with adopting such a coding habit? Is there any reason why I should prefer, in general, assigning a returned shared pointer to another shared pointer object rather than binding it to a reference?
This is just a remake of the old question of whether capturing a const reference to a temporary is more efficient than creating a copy. The simple answer is that it isn't. In the line:
// std::shared_ptr<Widget> bar();
std::shared_ptr<Widget> const & pWidget = bar();
The compiler needs to create a local unnamed variable (not temporary), initailize that with the call to bar() and then bind the reference to it:
std::shared_ptr<Widget> __tmp = bar();
std::shared_ptr<Widget> const & pWidget = __tmp;
In most cases it will avoid the creation of the reference and just alias the original object in the rest of the function, but at the end of the day whether the variable is called pWidget or __tmp and aliased won't give any advantage.
On the contrary, for the casual reader, it might look like bar() does not create an object but yield a reference to an already existing std::shared_ptr<Widget>, so the maintainer will have to seek out where bar() is defined to understand whether pWidget can be changed outside of the scope of this function.
Lifetime extension through binding to a const reference is a weird feature in the language that has very little practical use (namely when the reference is of a base and you don't quite care what the exact derived type returned by value is, i.e. ScopedGuard).
You may have the optimization backwards:
struct X
{
// ...
std::shared_ptr<Widget> const& bar() const
{
// ...
return pWidget;
}
// ...
std::shared_ptr<Widget> pWidget;
};
// ...
// X x;
std::share_ptr<Widget> pWidget = x.bar();
As bar is returning a member variable, it must take a copy of the shared_ptr in your version. If you return the member variable by reference the copy can be avoided.
This doesn't matter in both your original version and the version shown above, but would come up if you called:
x.bar()->baz()
In your version a new shared_ptr would be created, and then baz would be called.
In my version baz is called directly on the member copy of the shared_ptr, and the atomic reference increment/decrement is avoided.
Of course the cost of the shared_ptr copy constructor (atomic increment) is very small, and not even noticable in all but the most performance-sensetive applications. If you are writing a performance sensetive application than the better option would be to manage memory manually with a memory pool architecture and then to (carefully) use raw pointers instead.
Adding on top of what David RodrÃguez - dribeas said namely, binding to a const reference doesn't save you from making the copy and the counter is incremented anyway, the following code illustrates this point:
#include <memory>
#include <cassert>
struct X {
std::shared_ptr<int> p;
X() : p{new int} {}
std::shared_ptr<int> bar() { return p; }
};
int main() {
X x;
assert(x.p.use_count() == 1);
std::shared_ptr<int> const & p = x.bar();
assert(x.p.use_count() == 2);
return 0;
}
set<string> foo {
set<string> a;
// operation on a
return a;
}
Is there any performance difference if I do:
set<string>& foo {
set<string> a;
// ops on a
return a;
}
If so, my understanding is that a will be allocated on stack. After foo() returns,
the memory space will be reclaimed. How can we reference to a memory which is claimed?
In case B, any actual use of the returned value results in undefined behavior. You are not allowed to return a local automatic variable by reference and expect anyone to be able to access it.
See this live work space warning message. Your compiler will usually warn you when you do something like that, but relying on it is not always advised.
Note that in C++11, the first example is highly efficient. Betweeen lvalue reference based move and NRVO, the cost to return a local std::vector<std::string> by value is on the order of a few ifs and copying a 32 bits of memory, or in some cases less (ie, actually zero cost, because the std::set gets constructed in the callers scope directly).
There is no point discussing performance of a code which is not correct, like your second snippet, which behaviour is undefined (this will normally make your program crash). You cannot return references to automatic objects (allocated on stack), local to the function.
It would be ok if, for example, your foo function was a member function of a class, and was returning a reference to a member of the class:
class C {
public:
set<string>& foo1 { return a_; }
set<string> foo2 { return a_; }
private:
set<string> a_;
}
In the above example foo1 wil be more efficient than foo2 cause it will not create any new object, just return a reference to the existing one.