This question already has answers here:
Why do const references extend the lifetime of rvalues?
(2 answers)
Why doesn't a const reference extend the life of a temporary object passed via a function?
(4 answers)
Closed 13 days ago.
Someone asked this code in a Chinese QA forum
const string &a = "abcdefg";
cout << a << endl;
At first I thought it's illegal. Even if it can compile, it would crush when to use a, because what its reference was destructed. Until I tried my code:
class A
{
public:
A();
A(int a);
A(const string& name, int _a);
A(const A& o);
A(A&& o) noexcept;
A(std::initializer_list<A>);
virtual ~A();
A& operator=(const A& o);
A& operator=(A&& o);
int GetValue() const;
};
void test()
{
const A& a = 123;
cout << a.GetValue() << endl;
}
[![enter image description here][1]][1]
The destructor happens after calling a.GetValue(). How do I explain this?
[1]: https://i.stack.imgur.com/8qIUQ.png
Related
This question already has answers here:
Passing rvalue references between functions
(1 answer)
Rvalue Reference is Treated as an Lvalue?
(4 answers)
Closed 8 months ago.
void test(Foo&& a)
{
cout << "rvalue parameter" << endl;
}
void test(const Foo& a)
{
cout << "lvalue parameter" << endl;
}
it is my test program.
int main()
{
Foo&& a = Foo();
test(a);
return 0;
}
the result is that it will call the function test(const Foo& a).
why a will be regard as Foo& and compiler choose the second funtion.
I can't understand why a.funct() can be the left operand of the assignment operator even if funct() is not returning a l-value reference.
class A
{
public:
A funct () {A x; return x;}
};
int main ()
{
A a,b; a.funct()=b;
}
In the auto generated methods for the class, there is
A& operator = (const A&);
which make a.funct() = b legal.
To forbid affectation to rvalue, you may, since C++11, write and implement
A& operator = (const A&) &; // Note the last &
so assignation would only work for lvalue.
In the code, funct should return a variable that can be assigned to.
Note that the code in funct is very dangerous too if it were to be returned by reference; the local variable x will go out of scope once the function ends and the variable returned will cause undefined behaviour as its destructor will have been called.
Your assumption is wrong. Your code is perfectly valid.
Try this code:
#include <string>
#include <iostream>
class A
{
std::string m_name;
public:
A(const std::string& name) :m_name(name) {}
A funct() { A x("intern"); return x; }
A& operator=(const A& a)
{
m_name += a.m_name;
return *this;
}
void print() { std::cout << m_name << std::endl; }
};
int main()
{
A a("A"), b("B"); (a.funct() = b).print();//prints "internB"
}
There are 2 identical functions. One takes the argument with const keyword and another - without.
void A(const int* p);
void A(int* p);
int main()
{
int x;
A(&x);
return 0;
}
void A(const int* p)
{
cout << "2" << endl;
}
void A(int* p)
{
cout << "1" << endl;
}
Is it function overloading?
Why function without const will be called it my case?
Is it function overloading?
Yes. The two functions have the same name but different parameters, so they are overloads.
Why function without const will be called it my case?
Because x is not const. Try with a pointer to a const int, and you'll get the other overload:
const int y;
A(&y);
I think this is variation of the initial question :
from Stroustrup's tour of c++
template<typename T>
class C {
...
public:
...
T& operator[](int i);
const T& operator[](int i) const;
}
So as I understand it, the second method will target cases where the this-object is not intended to be modified.
I just wonder if the compiler is able to accurately guess that in every relevent case..
Lets say we have the following code:
std::vector<int> f()
{
std::vector<int> y;
...
return y;
}
std::vector<int> x = ...
x = f();
It seems the compiler has two approaches here:
(a) NRVO: Destruct x, then construct f() in place of x.
(b) Move: Construct f() in temp space, move f() into x, destruct f().
Is the compiler free to use either approach, according to the standard?
The compiler may NRVO into a temp space, or move construct into a temp space. From there it will move assign x.
Update:
Any time you're tempted to optimize with rvalue references, and you're not positive of the results, create yourself an example class that keeps track of its state:
constructed
default constructed
moved from
destructed
And run that class through your test. For example:
#include <iostream>
#include <cassert>
class A
{
int state_;
public:
enum {destructed = -2, moved_from, default_constructed};
A() : state_(default_constructed) {}
A(const A& a) : state_(a.state_) {}
A& operator=(const A& a) {state_ = a.state_; return *this;}
A(A&& a) : state_(a.state_) {a.state_ = moved_from;}
A& operator=(A&& a)
{state_ = a.state_; a.state_ = moved_from; return *this;}
~A() {state_ = destructed;}
explicit A(int s) : state_(s) {assert(state_ > default_constructed);}
friend
std::ostream&
operator<<(std::ostream& os, const A& a)
{
switch (a.state_)
{
case A::destructed:
os << "A is destructed\n";
break;
case A::moved_from:
os << "A is moved from\n";
break;
case A::default_constructed:
os << "A is default constructed\n";
break;
default:
os << "A = " << a.state_ << '\n';
break;
}
return os;
}
friend bool operator==(const A& x, const A& y)
{return x.state_ == y.state_;}
friend bool operator<(const A& x, const A& y)
{return x.state_ < y.state_;}
};
A&& f()
{
A y;
return std::move(y);
}
int main()
{
A a = f();
std::cout << a;
}
If it helps, put print statements in the special members that you're interested in (e.g. copy constructor, move constructor, etc.).
Btw, if this segfaults on you, don't worry. It segfaults for me too. Thus this particular design (returning an rvalue reference to a local variable) is not a good design. On your system, instead of segfaulting, it may print out "A is destructed". This would be another sign that you don't want to do this.
I have this snippet of the code:
header
class A {
private:
int player;
public:
A(int initPlayer = 0);
A(const A&);
A& operator=(const A&);
~A();
void foo() const;
friend A& operator=(A& i, const A& member);
};
operator=
A& operator=(A& i, const A& member){
i(member.player);
return i;
}
and I have row in my code:
i = *pa1;
A *pa1 = new A(a2);
at the beginning i was int
how can I fix it, thanks in advance
I have an error must be non-static function
The assignment operator for a class must be a member function, not a friend.
A& operator=( const A& member){
this->player = member.player);
return *this;
}
If you want to convert an A class object to an integer, provide a named conversion function such as ToInt().
As with all your questions, this could easily have been answered by reading a C++ text book. This is the last of such questions from you I will be answering.