Just a quick question about a function like this:
class Test {
public:
Test(vector<int>& v) {
v_ = v;
}
private:
std::vector<int> v_;
};
What's the difference between using Test(vector<int>& v) and Test(vector<int> v)? I seem to know that the first one should be faster since it is pass-by-reference. But I'm not so sure whether there are other differences.
The difference is that with Test(vector<int>& v) (which BTW is an lvalue reference) v refers to the original object, while with Test(vector<int> v) you have a copy. The following example code demonstrates the difference with an int and a normal function (note that for int, pass-by-value is actually faster!):
#include <iostream>
int global_i;
void pass_by_value(int i)
{
std::cout << "pass by value:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
void pass_by_reference(int& i)
{
std::cout << "pass by reference:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
i++;
std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
void pass_by_const_reference(int const& i)
{
std::cout << "pass by const reference:\n";
std::cout << "initially: i = " << i << ", global_i = " << global_i << "\n";
// i++; not allowed!
// std::cout << "after i++: i = " << i << ", global_i = " << global_i << "\n";
global_i++;
std::cout << "after global_i++: i = " << i << ", global_i = " << global_i << "\n";
}
int main()
{
global_i = 1;
pass_by_value(global_i);
global_i = 1;
pass_by_reference(global_i);
global_i = 1;
pass_by_const_reference(global_i);
}
The output of this is:
pass by value:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 1
after global_i++: i = 2, global_i = 2
pass by reference:
initially: i = 1, global_i = 1
after i++: i = 2, global_i = 2
after global_i++: i = 3, global_i = 3
pass by const reference:
initially: i = 1, global_i = 1
after global_i++: i = 2, global_i = 2
As you see, with call by value, the argument and the passed variable are completely separate. Incrementing the argument does not change the passed variable, and incrementing the passed variable does not change the argument. On the other hand, with pass by reference, the argument just gives access to the passed variable: It doesn't matter which one you increment because effectively, they are the same. With pass by const reference, they are also the same, but you are not allowed to mosify the argument (there are ways around this, though). However, the argument still reflects any changes to the passed variable.
Those are the differences in functionality. However there are some more differences: For pass by value and pass by const reference, you can use an rvalue, like call_by_value(2) or call_by_const_reference(2). For call by value, it's obvious what happens: The argument gets the value 2, and that's it. However for const reference, there's an object expected (you could for example take the address of that object in the function). Therefore in that case a temporary object is created. For call by non-const reference, you cannot pass an rvalue.
C++11 adds another type to the mix, namely rvalue references. Those are denoted with && instead of &. Inside the function they behave exactly like normal (lvalue) references, but they differ in that they can be bound to rvalues, even if they are not const. Moreover, if you use them as return type, the call expression will be of rvalue type as if you had returned a value. Especially, you would not be able to pass the result of a function returning an rvalue reference to a function expecting an lvalue reference, just like you couldn't do that with the literal 2.
There are no rvalue references in your code, just a lot of unnecessary copying.
However, since we're on the topic, here's the right way to write this with move semantics:
Test(std::vector<int> v) // by value!
: v_(std::move(v))
{
}
In the pre-11 world, the next best way is to take the argument by const-reference and copy it:
Test(std::vector<int> const & v)
: v_(v)
{
}
Related
#include <iostream>
#include <functional>
using Callback = std::function<void(const int)>;
int main() {
Callback testCall = [](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
};
int num = 42;
testCall(num);
std::cout << "main: " << num << " - " << &num << std::endl;
}
Possible output:
callback: 42 - 000000B19197F618
main: 42 - 000000B19197F694
As you can see, even if i assign a lambda function which takes the parameter by reference it still uses a copy.
Is that correct?
If yes, why does it still compile? Why is there at least not a warning about the discrepancy between the Callback declaration parameters and the assigned lambda. (const int &num vs const int num)
When not usingconst it does not compile.
PS. if you find a better title, feel free to edit.
This is because testCall is a functor object that catch its parameter by copy and then call the lambda on it.
Try:
Callback f = [](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
};
int main() {
int num = 999;
std::cout << "callback: " << num << " - " << &num << std::endl;
f(num);
[](const int &num) {
std::cout << "callback: " << num << " - " << &num << std::endl;
}(num);
}
you will see something like:
callback: 999 - 0x7ffeed60a9bc
callback: 999 - 0x7ffeed60a994
callback: 999 - 0x7ffeed60a9bc
which means that callBack is not the function by itself but an indirection to the function. And there is no problem regarding types...
Answer to this may helps you to understand what happens under the hood: How std::function works
you know that the compiler transforms a lambda expression into some kind of functor:
the captured variables become data members of this functor. Variables captured by value are copied into data members of the functor. These data members have the same constness as the captured variables et cetera...
Now I wonder if it's possible to catch the address of this hidden object generated from the compiler behind the scenes
I give you a simple snippet of (WRONG) code just to show my intentions:
#include <iostream>
using namespace std;
class MetaData
{
public:
void printAddress()
{
cout << "\n printAddress:Instance of MetaData at &" << this;
}
};
int main()
{
MetaData md1;
cout << "\n &md1 = " << &md1 << "\n";
md1.printAddress();
cout << "\n\n--------------------\n\n";
int i = 5;
auto x = [i]() mutable {
//cout << "\n The address of the functor is &" << this; // ERROR ! ! !
cout << "\n Hello from Lambda ";
cout << "\n &i = " << &i << " ++i ==> " << ++i << endl; };
x(); // executing lambda
auto y = x; // y is constructed with copy ctor
y();
}
Link to Coliru
I'd like hidden functor to behave like MetaDatas.
Can someone clear my mind?
Thanks for your time.
Syntax would be:
auto x = [&](){ std::cout << &x; }; // but it is illegal too:
// variable 'x' declared with deduced type 'auto' cannot appear in its own initializer
Possible work-around is usage of Y-combinator, something like:
auto x = [i](auto& self) mutable {
cout << "\n The address of the functor is &" << &self;
cout << "\n Hello from Lambda ";
cout << "\n &i = " << &i << " ++i ==> " << ++i << endl; };
x(x); // executing lambda
Demo
So my question is pretty simple, tho I haven't been able to find an answer already so I'm asking here.
I curious to know whether I can return an std:: pair reference from a function, and have the calling function modify its values. Here's an example of what I mean:
struct PairStruct {
using PairType = std::pair<size_t, size_t>;
PairStruct() : m_pair(std::make_pair(0, 0)) {}
void modifyRefInternal() {
auto pair = getPairRef();
std::cout << "start - first: " << pair.first << ", second: " << pair.second << "\n";
pair.first++;
pair.second++;
std::cout << "end - first: " << pair.first << ", second: " << pair.second << "\n";
}
void modifyPtrInternal() {
auto pair = getPairPtr();
std::cout << "start - first: " << pair->first << ", second: " << pair->second << "\n";
pair->first++;
pair->second++;
std::cout << "end - first: " << pair->first << ", second: " << pair->second << "\n";
}
PairType &getPairRef() {
return m_pair;
}
PairType *getPairPtr() {
return &m_pair;
}
PairType m_pair;
};
int main(int argc, char ** args)
{
PairStruct *pairInst = new PairStruct;
// Test with reference
std::cout << "Reference test.\n";
pairInst->modifyRefInternal();
std::cout << "\n";
pairInst->modifyRefInternal();
std::cout << "\n";
// Test with ptr
std::cout << "Ptr test.\n";
pairInst->modifyPtrInternal();
std::cout << "\n";
pairInst->modifyPtrInternal();
delete pairInst;
return 0;
}
As expected when I use a pointer it correctly modyfies the values, this is not the case when returning a reference. Here's the output of this program:
Reference test.
start - first: 0, second: 0
end - first: 1, second: 1
start - first: 0, second: 0
end - first: 1, second: 1
Ptr test.
start - first: 0, second: 0
end - first: 1, second: 1
start - first: 1, second: 1
end - first: 2, second: 2
This is going to seem very trivial, however, I'd like to know why I can't use the referenced pair in this case. Thanks!
With
auto pair = getPairRef();
the variable pair is deduced as a value, not a reference.
You need to explicitly make it a reference:
auto& pair = getPairRef();
Just write in the member function modifyRefInternal
decltype(auto) pair = getPairRef();
^^^^^^^^^
The test method on the following class does not have the effect I would expect it to. I have a suspicion it is something to do with the fact that the invocation of emplace_back somehow invalidates the reference obtained via the subscript.
Either way I would expect the second print in test to result in
v[0] = 1
however both result in
v[0] = 5
suggesting that the assignment does not take place.
class FooBar {
vector<size_t> v;
public:
size_t add(size_t x) {
cout << "add(" << x << ")" << endl;
size_t K(v.size());
v.emplace_back(x);
return K;
}
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
v[idx] = add(0);
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
};
int main(int argc, char* argv[])
{
FooBar f;
f.add(5);
f.test(0);
}
I know that I can get around the problem by creating a temporary to store the result of add and then perform the assignment but I am interested as to why I cannot use just a straight assignment and why I do not get any kind of error when attempting to perform this.
Compiled and tested with MSVC (Visual Studio 2015).
The line
v[idx] = add(0);
is cause for undefined behavior. You are modifying the contents of v in add while assuming that v[idx] will be valid.
For predictable behavior, you can use:
void test(size_t idx) {
cout << "v[" << idx << "] = " << v[idx] << endl;
size_t val = add(0);
v[idx] = val;
cout << "v[" << idx << "] = " << v[idx]<< endl;
}
This question already has answers here:
How to print function pointers with cout?
(7 answers)
Closed 9 years ago.
I'm not clear on what the values that are being returning from calling:
&next, fp, *fp, &return_func_ptr, fp_ptr, &fp_ptr, *fp_ptr
They all seem to give me the value 1. What does it mean?
Also, how would I declare
int (*return_f())(char)
to receive a parameter without using typedef?
#include <iostream>
int next(int n){
return n+99;
}
// returns pointer to a function
typedef int (*fptr)(int); // using typdef
fptr return_func_ptr(){
return next;
}
int f(char){
return 0;
}
int (*return_f())(char){ // how do you pass a parameter here?
// std::cout << "do something with " << param << std::endl;
return f;
}
int main()
{
int x = 5;
// p points to x
int *p = &x;
std::cout << "x=" << x << std::endl; // 5, value of x
std::cout << "&x=" << &x << std::endl; // 0x7fff6447a82c, address of x
std::cout << "p=" << p << std::endl; // 0x7fff6447a82c, value of p is address of x
std::cout << "*p=" << *p << std::endl; // 5, value of x (p dereferenced)
std::cout << "&p=" << &p << std::endl; // 0x7fff6447a820, address of p pointer
// change value of x thru p
// p = 6; // error, can't set int* to int
*p = 6;
std::cout << "x=" << x << std::endl; // 6
int y = 2;
// int *q = y; // error can't initiate with type int, needs int*
// pointer to a function
int (*fp)(int);
std::cout << "&fp=" << &fp << std::endl; // 0x7fff66da6810, address of pointer fp
std::cout << "fp=" << fp << std::endl; // 0, value of pointer fp
fp = &next; // fp points to function next(int)
fp = next;
std::cout << "&next=" << &next << std::endl; // 1, address of function?
std::cout << "fp=" << fp << std::endl; // 1, value is address of function?
std::cout << "&fp=" << &fp << std::endl; // 0x7fff66da6810, address of pointer fp?
std::cout << "*fp=" << *fp << std::endl; // 1, address of function?
// calling function thru pointer
int i = 0;
i = (*fp)(i);
std::cout << "i=" << i << std::endl; // 99
i = fp(i);
std::cout << "i=" << i << std::endl; // 198
// function returns pointer to function
fptr fp_ptr = return_func_ptr();
std::cout << "&return_func_ptr=" << &return_func_ptr << std::endl; // 1
std::cout << "fp_ptr=" << *fp_ptr << std::endl; // 1
std::cout << "&fp_ptr=" << *fp_ptr << std::endl; // 1
std::cout << "*fp_ptr=" << *fp_ptr << std::endl; // 1
int j = fp_ptr(1);
std::cout << "j=" << j << std::endl; // 100
}
There is some pointer here who seems not clear :
// pointer to a function
int (*fp)(int);
std::cout << "&fp=" << &fp << std::endl; // 0x7fff66da6810, address of pointer fp
std::cout << "fp=" << fp << std::endl; // 0, value of pointer fp
Here fp is undefined. Those lines have an undefined behaviour.
After that :
// function returns pointer to function
fptr fp_ptr = return_func_ptr();
std::cout << "&return_func_ptr=" << &return_func_ptr << std::endl; // 1
std::cout << "fp_ptr=" << *fp_ptr << std::endl; // 1
std::cout << "&fp_ptr=" << *fp_ptr << std::endl; // 1
// ^^^^^^^^^^ ^^^^^^^
std::cout << "*fp_ptr=" << *fp_ptr << std::endl; // 1
There are two things here :
On the line I pointed, I'm not sure it is what you wanted to test.
Also, cout doesn't have an overload to take a function pointer, it will take a bool instead. So it should be :
std::cout << "fn_ptr=" << reinterpret_cast<void*>( fn_ptr ) << std::endl;
I would suggest you to read this article about function pointer, it explains almost all you need to know : http://www.learncpp.com/cpp-tutorial/78-function-pointers/
std::cout << "fp_ptr=" << *fp_ptr << std::endl;
should be
std::cout << "fp_ptr=" << (void*)fp_ptr << std::endl;
The cout operator doesn't have an overload for a function pointer, so it uses bool instead. That's why you always get 1 as output. When I compile your code, I even get a warning for that, telling me that it will always evaluate to true. You should switch on all warnings and try to get rid of them.