Int variable's value won't change after being moved - vector

I've read the basics of move semantics and I did a couple of tests.
Case #1:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
string st = "hello";
vector<string> vec;
vec.push_back(st);
cout << st;
cin.get();
}
In this case, the program will not print anything because "hello" has been moved to vector[0].
Case #2:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int num=5;
vector<int> vec;
vec.push_back(num);
cout << num;
cin.get();
}
Why does the program print "5"? I thought num would be 0 or something undefined.

Case #1 should print "hello". If not then your compiler has bug and you should upgrade to a newer version or complain to who ever wrote it.
Case #2 correctly prints "5".
However, if you changed line 10 in case 2 from:
vec.push_back(st);
to:
vec.push_back(std::move(st));
you will get what you expected, a print to console of "" because vector "stole" the value in st.
int is a fundamental type in c++ and trying to "steal" from an int variable doesn't realy work since it does't own any resource.
std::string is a resource owner. It "owns" a char array (this isn't always true, but for simplicity we will pretend it is).
So when we pass std::move(st) to push_back we are calling the T&& overload of push_back which does the "stealing" by calling the move constructor of std::string which releases st's handle and gives it to the newly created std::string inside vec.
But if we called push_back like this: vec.push_back(st); this will not "steal" any thing. Instead, it will call the const T& overload of push_back which just does a simple copy by calling the normal copy constructor of std::string such that we will have st set to "hello" and vec[0] set with its own version of "hello".
Try this code below to see how all this works out:
#include <iostream>
#include <vector>
using namespace std;
struct Foo
{
Foo() // default constructor
{
cout << "Foo()" << endl;
}
Foo(const Foo&) // copy constructor
{
cout << "Foo(const Foo&)" << endl;
}
Foo(Foo&&) // move constructor
{
cout << "Foo(Foo&&)" << endl;
}
Foo& operator=(const Foo&) // copy assignment operator
{
cout << "operator=(const Foo&)" << endl;
return *this;
}
Foo& operator=(Foo&&) // move assignment operator
{
cout << "operator=(Foo&&)" << endl;
return *this;
}
~Foo()
{
cout << "~Foo()" << endl;
}
};
int main()
{
Foo f; // print: Foo();
vector<Foo> vec;
vec.push_back(f); // print: Foo(const Foo&)
vec.push_back(std::move(f)); // print: Foo(Foo&&)
Foo f2; // print: Foo()
f2 = f; // print: operator=(const Foo&)
f2 = std::move(f); // print: operator=(Foo&&)
cin.get();
}

Related

Converting std::vector from BYTE to int

Code:
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
void CCreateReportDlg::GetColumnIndexesToExclude()
{
const CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
ByteVector vData = theApp.GetProfileVector(strSection, _T("AssignStatesEx"));
ColumnIndexVector vTemp(vData.begin(), vData.end()); // This converts BYTE to int
m_vColumnIndexesToExclude = vTemp;
}
Is there any way to avoid the requirement for vTemp without manually iterating vData and casting from BYTE to int?
Yes, just use assign(). IDK if you need to use clear() as well, but probably not. Just step through the runtime code the first time to know.
m_vColumnIndexesToExclude.assign(vData.begin(), vData.end());
Here's a test program:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
int main(int argc, char* argv[])
{
cout << "Test" << endl;
ByteVector bytes = {'A', 'B', 'C', 'D'};
ColumnIndexVector colVector;
for ( auto _val: bytes)
{
cout << _val << endl;
}
colVector.assign(bytes.begin(), bytes.end());
for ( auto _val : colVector)
{
cout << _val << endl;
}
return 0;
}

Qt5: compile error while QSharedPointer<const T>::create()

Is it "expected" for QSharedPointer::create() not to work or is it a bug? I get an error:
/usr/include/qt5/QtCore/qsharedpointer_impl.h:439:9: error:
invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
new (result.data()) T(std::forward<Args>(arguments)...);
casting from nonconst shared pointer and constructor from raw const pointer work.
I got this for Qt5.7.0 and Qt5.10.0.
Here is a minimal example:
#include <QSharedPointer>
struct A {};
int main(int argc, char *argv[])
{
auto ca = QSharedPointer<const A>::create();
return 0;
}
Here is one file (not minimal) example but with few working cases, 2 not working and a debug. Commented defines are for "not compiling" parts.
#include <QSharedPointer>
#include <QDebug>
#define FROM_PTR
//#define CONST_CREATE
#define FROM_RAW_PTR
#define PERFECT_FORWARD_CREATE
//#define PERFECT_FORWARD_CREATE_CONST
#define BUILTIN_CAST
class A
{
public:
A() = default;
A(int i) : _i{i} {}
void foo() const { qDebug() << "const foo" << _i; }
void foo() { qDebug() << "foo" << ++_i; }
private:
int _i{0};
};
using ASPtr = QSharedPointer<A>;
using ASCPtr = QSharedPointer<const A>;
int main(int argc, char *argv[])
{
Q_UNUSED(argc)
Q_UNUSED(argv)
#ifdef FROM_PTR
qDebug() << "FROM_PTR";
auto a1 = ASPtr::create();
a1->foo();
auto ca1 = static_cast<ASCPtr>(a1);
ca1->foo();
qDebug() << "\n";
#endif // FROM_PTR
#ifdef CONST_CREATE
qDebug() << "CONST_CREATE";
auto ca2 = ASCPtr::create();
ca2->foo();
qDebug() << "\n";
#endif // CONST_CREATE
#ifdef FROM_RAW_PTR
qDebug() << "FROM_RAW_PTR";
auto ca3 = ASCPtr(new const A);
ca3->foo();
qDebug() << "\n";
#endif // FROM_RAW_PTR
#ifdef PERFECT_FORWARD_CREATE
qDebug() << "PERFECT_FORWARD_CREATE";
auto a2 = ASPtr::create(10);
a2->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef PERFECT_FORWARD_CREATE_CONST
qDebug() << "PERFECT_FORWARD_CREATE_CONST";
auto ca4 = ASCPtr::create(20);
ca4->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef BUILTIN_CAST
qDebug() << "BUILTIN_CAST";
QSharedPointer<A> a3 = ASPtr::create();
a3->foo();
auto ca4 = a3.constCast<const A>();
ca4->foo();
qDebug() << "\n";
#endif // BUILTIN_CAST
return 0;
}
That is a known Qt bug (QTBUG-49748). Although it is marked as resolved in Qt 5.6.0, the bug is still present as pointed out in the comments.
Why is this happening?
Look at the implmentation of the class QSharedPointer qsharedpointer_impl.h.
In particular the line:
new (result.data()) T(std::forward<Args>(arguments)...);
uses the result.data() as the new expression placement params. Unfortunately, one can not use a const pointer as a placement param (have a look at this question here on SO for more details).
Hence, there's not much you can do except reporting this to Qt developers via the official bug tracker.
You may have a look at the smart pointers provided by the standard library (e.g. std::shared_ptr) if you are not forced to use Qt ones.
UPDATE
As reported in Qt bug tracker, this bug was fixed in version 5.11 (here is the related commit). Basically, they used std::remove_cv to remove the topmost const from the type specified.

'this' pointer changes in c++11 lambda

I found a very strange problem with this pointer in c++11's lambda.
#include <string>
#include <iostream>
using namespace std;
#include <boost/signals2.hpp>
boost::signals2::signal<void()> sig;
struct out {
void print_something() {
cout << "something" << endl;
}
out() {
auto start = [&] {
cout << "this in start: " << this << endl;
this->print_something();
};
cout << "this in constructor: " << this << endl;
// sig.connect(start);
sig.connect([&] {
cout << "this in signal: " << this << endl;
start();
});
this->print_something();
}
};
int main() {
out o;
sig();
}
The code prints three this(s) pointer at different location. I was expecting that all the three this pointer should be the same value, but they are not. Here's the output:
this in constructor: 00F3FABB
something
this in signal: 00F3FABB
this in start: 00F3FB00
something
Question 1: Why is this in start has different value? How to correct it?
Question 2: Since the this in start is a different pointer, it shouldn't be able to call print_something(). I would expect a crash on this but it works fine. Why?
You capture start by reference, but the variable start and the contained lambda function get destroyed at the end of out().
Later the signal handler tries to call start(), but the lambda function doesn't exist anymore. Maybe the memory where its this was stored was overwritten in the mean time, causing unexpected output.
The call to print_something() doesn't crash despite of the invalid this because the function doesn't actually try to use this. The printing in the function is independent of this and the lookup of print_somethings address can happen at compile time so that calling the function doesn't access this at runtime.

QT QString from QDataStream

I'm working with a buffer and I'm trying to get a string from it, but isnt working...
Example:
*void myFunc(QDataStream& in)
{
quint8 v;
in >> v;
// Ok, I caught v value successfuly
QString s;
in >> s;
// Didnt work :<
}*
The string lenght is stored on 2 first bytes...
Thanks
If the string was not written as a QString, you need to read its length and content separately.
quint8 v;
in >> v;
quint16 length = 0;
in >> length;
// the string is probably utf8 or latin
QByteArray buffer(length, Qt::Uninitialized);
in.readRawData(buffer.data(), length);
QString string(buffer);
You might have to change the endianness of the QDataStream with QDataStream::setByteOrder before reading the 16-bit length.
We should really see the writing code and how you create the QDataStream. I tried with the following sample, and in this case your function works very well:
#include <QCoreApplication>
#include <QDebug>
#include <QDataStream>
#include <QBuffer>
void myFunc(QDataStream& in)
{
quint8 v;
in >> v;
qDebug() << v;
// Ok, I caught v value successfuly
QString s;
in >> s;
qDebug() << s;
// Didnt work :<
}
int main(int argc, char ** argv) {
QCoreApplication a(argc, argv);
QBuffer buffer;
buffer.open(QBuffer::ReadWrite);
// write test data into the buffer
QDataStream out(&buffer);
quint8 ival = 42;
QString sval = "Qt";
out << ival;
out << sval;
// read back data
buffer.seek(0);
myFunc(out);
return a.exec();
}
Output when executed:
$ ./App
42
"Qt"

Qt Problems compiling using an extern variable

I have a rellly long process that produces about 700 Mb of a txt log output file. This is very hard to manage. So I want to divide the output in multiple smaller log files. This is what my main.cpp looks like
#include <QtGui/QApplication>
#include "mineedit.h"
#include "logoutput.h"
#include <iostream>
void messageHandling(QtMsgType type, const char *msg){
if (ERRORLOGGER.isEmpty()){
ERRORLOGGER = DEFERRORLOGGER;
}
std::cout << "In Message Handling" << std::endl;
std::cout << "Writing to file" << ERRORLOGGER.toStdString() << std::endl;
QFile file(ERRORLOGGER);
file.open(QFile::Append);
QTextStream stream(&file);
switch (type) {
case QtDebugMsg:
stream << msg << "\n";
file.close();
break;
case QtWarningMsg:
stream << "WARNING: " << msg << "\n";
file.close();
break;
case QtCriticalMsg:
stream << "CRITICAL: " << msg << "\n";
file.close();
break;
case QtFatalMsg:
stream << "FATAL: " << msg << "\n";
file.close();
abort();
}
}
int main(int argc, char *argv[])
{
ERRORLOGGER = DEFERRORLOGGER;
qInstallMsgHandler(messageHandling);
QApplication a(argc, argv);
MineEdit w;
w.show();
return a.exec();
}
[/CODE]
And my logoutput.h is like
#ifndef LOGOUTPUT_H
#define LOGOUTPUT_H
#include <QString>
//----------------------------For outputting an error file------------------------------
#define DEFERRORLOGGER "/home/aarelovich/Documents/log.err"
#define FOLDER_OUTPUT_LOG "./home/aarelovich/Documents"
extern QString ERRORLOGGER;
#endif // LOGOUTPUT_H
Now in a part of my code I do:
ERRORLOGGER = name_of_current_log_file.
However I get the following compilation errors:
obj/main.o: In function messageHandling(QtMsgType, char const*)':
/home/aarelovich/Dropbox/MineSim/main.cpp:8: undefined reference toERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:9: undefined reference to ERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:13: undefined reference toERRORLOGGER'
/home/aarelovich/Dropbox/MineSim/main.cpp:15: undefined reference to ERRORLOGGER'
obj/main.o: In functionmain':
/home/aarelovich/Dropbox/MineSim/main.cpp:40: undefined reference to ERRORLOGGER'
obj/mineedit.o:/home/aarelovich/Dropbox/MineSim/mineedit.cpp:101: more undefined references toERRORLOGGER' follow
collect2: ld returned 1 exit status
Can anyone please tell me what am I doing wrong? Or how I can dynamically change the output file in which I create my application log?
Thanks for any help
Your problem is probably related to extern variable.
Here is an example of how to use extern keyword in c++.
Beware that C++ and C have differences with extern keyword when linking.
Basicall what you need to do is
global.cpp:
// declaration of g_nValue
int g_nValue = 5;
main.cpp:
// extern tells the compiler this variable is declared elsewhere
extern int g_nValue;
int main()
{
g_nValue = 7;
return 0;
}
In your example if you use extern QString ERRORLOGGER; in logoutput.h,
this variable needs to be declared in another cpp just as explained in the link.
I hope this helps

Resources