Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Why the pointer of QVector always change when use QVector as parameter of signal?
Forum Updated to NodeBB v4.3 + New Features

Why the pointer of QVector always change when use QVector as parameter of signal?

Scheduled Pinned Locked Moved Unsolved General and Desktop
7 Posts 3 Posters 504 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Mozzie
    wrote on 15 Nov 2021, 02:47 last edited by
    #1

    Hi,
    Recently, I meet a very confuse problem. after a long time troubleshoot, I found the pointer of QVector always change when use QVector as parameter of signal. first I thought I might used the move constructor of Qvector QVector(QVector<T> &&), then I write a demo to test this, but actually, I did not call the move constructor but called the copy constuctor QVector(const QVector<T> &), and the pointer of the orignal QVector changed! I know when the slot is about to execute, the QVector will copy from the orignal QVector, but the orignal QVector should not be changed right? and there is a const key work to limit the parameter.

    my test code is:

    TestVector.h

    #ifndef TESTVECTOR_H
    #define TESTVECTOR_H
    
    #include <QObject>
    #include <QVector>
    #include "Vector.h"
    
    class TestVector : public QObject
    {
    	Q_OBJECT
    public:
    	explicit TestVector(QObject *parent = nullptr);
    
    public slots:
    	void handle(const Vector<float>& data);
    signals:
    	void dataReady(const Vector<float>& data);
    
    
    protected:
    };
    
    #endif // TESTVECTOR_H
    
    

    TestVector.cpp

    #include "TestVector.h"
    
    TestVector::TestVector(QObject *parent) : QObject(parent)
    {
    	connect(this, &TestVector::dataReady, this, &TestVector::handle, Qt::QueuedConnection);
    }
    
    void TestVector::handle(const Vector<float>& data)
    {
    	QVector<float> _data;
    	_data.resize(data.size());
    	for (int i = 0; i < data.size(); i++) {
    		_data[i] = data[i] + 1;
    	}
    }
    
    

    Vector.h

    #ifndef VECTOR_H
    #define VECTOR_H
    
    #include <QVector>
    #include <QDebug>
    
    template<typename T>
    class Vector : public QVector<T>
    {
    public:
    	Vector() : QVector<T>() {
    		qDebug() << __FUNCTION__ << __LINE__;
    	}
    	Vector(const Vector<T>& other) : QVector<T>(other) {
    		qDebug() << __FUNCTION__ << __LINE__;
    	}
    	Vector(Vector<T> && other) : QVector<T>(other) {
    		qDebug() << __FUNCTION__ << __LINE__;
    	}
    	QVector<T> &operator=(Vector<T> &&other) {
    		qDebug() << __FUNCTION__ << __LINE__;
    		return QVector<T>::operator=(other);
    	}
    
    	virtual ~Vector() {
    		qDebug() << __FUNCTION__ << __LINE__;
    	}
    };
    
    Q_DECLARE_METATYPE(Vector<float>)
    
    #endif // VECTOR_H
    
    

    part of test code:

    	{
    		qRegisterMetaType<Vector<float>>();
    		TestVector* test = new TestVector;
    		QThread* thread = new QThread;
    		test->moveToThread(thread);
    
    		thread->start();
    
    
    		m_data.resize(1024 * 32);
    
    		for (int i = 0; i < 1000; i++) {
    			qDebug() << "data" << m_data.data();
    //			Vector<float> _data(data);
    			emit test->dataReady(m_data);
    		}
    	}
    

    test result
    1.PNG

    J 1 Reply Last reply 15 Nov 2021, 05:30
    0
    • B Offline
      B Offline
      Bonnie
      wrote on 15 Nov 2021, 05:21 last edited by Bonnie
      #2

      Hey I just test with your code. If you change m_data.data() to m_data.constData() then you'll have the same address.
      I think maybe because when you call QVector::data() it will call something like "detach" and performs a deep copy of the orignal data when there're other copies.

      1 Reply Last reply
      2
      • M Mozzie
        15 Nov 2021, 02:47

        Hi,
        Recently, I meet a very confuse problem. after a long time troubleshoot, I found the pointer of QVector always change when use QVector as parameter of signal. first I thought I might used the move constructor of Qvector QVector(QVector<T> &&), then I write a demo to test this, but actually, I did not call the move constructor but called the copy constuctor QVector(const QVector<T> &), and the pointer of the orignal QVector changed! I know when the slot is about to execute, the QVector will copy from the orignal QVector, but the orignal QVector should not be changed right? and there is a const key work to limit the parameter.

        my test code is:

        TestVector.h

        #ifndef TESTVECTOR_H
        #define TESTVECTOR_H
        
        #include <QObject>
        #include <QVector>
        #include "Vector.h"
        
        class TestVector : public QObject
        {
        	Q_OBJECT
        public:
        	explicit TestVector(QObject *parent = nullptr);
        
        public slots:
        	void handle(const Vector<float>& data);
        signals:
        	void dataReady(const Vector<float>& data);
        
        
        protected:
        };
        
        #endif // TESTVECTOR_H
        
        

        TestVector.cpp

        #include "TestVector.h"
        
        TestVector::TestVector(QObject *parent) : QObject(parent)
        {
        	connect(this, &TestVector::dataReady, this, &TestVector::handle, Qt::QueuedConnection);
        }
        
        void TestVector::handle(const Vector<float>& data)
        {
        	QVector<float> _data;
        	_data.resize(data.size());
        	for (int i = 0; i < data.size(); i++) {
        		_data[i] = data[i] + 1;
        	}
        }
        
        

        Vector.h

        #ifndef VECTOR_H
        #define VECTOR_H
        
        #include <QVector>
        #include <QDebug>
        
        template<typename T>
        class Vector : public QVector<T>
        {
        public:
        	Vector() : QVector<T>() {
        		qDebug() << __FUNCTION__ << __LINE__;
        	}
        	Vector(const Vector<T>& other) : QVector<T>(other) {
        		qDebug() << __FUNCTION__ << __LINE__;
        	}
        	Vector(Vector<T> && other) : QVector<T>(other) {
        		qDebug() << __FUNCTION__ << __LINE__;
        	}
        	QVector<T> &operator=(Vector<T> &&other) {
        		qDebug() << __FUNCTION__ << __LINE__;
        		return QVector<T>::operator=(other);
        	}
        
        	virtual ~Vector() {
        		qDebug() << __FUNCTION__ << __LINE__;
        	}
        };
        
        Q_DECLARE_METATYPE(Vector<float>)
        
        #endif // VECTOR_H
        
        

        part of test code:

        	{
        		qRegisterMetaType<Vector<float>>();
        		TestVector* test = new TestVector;
        		QThread* thread = new QThread;
        		test->moveToThread(thread);
        
        		thread->start();
        
        
        		m_data.resize(1024 * 32);
        
        		for (int i = 0; i < 1000; i++) {
        			qDebug() << "data" << m_data.data();
        //			Vector<float> _data(data);
        			emit test->dataReady(m_data);
        		}
        	}
        

        test result
        1.PNG

        J Offline
        J Offline
        jsulm
        Lifetime Qt Champion
        wrote on 15 Nov 2021, 05:30 last edited by
        #3

        @Mozzie said in Why the pointer of QVector always change when use QVector as parameter of signal?:

        Qt::QueuedConnection

        This is why: Qt::QueuedConnection is usually used for signals/slots across threads and in this case all parameters are copied. Do not use queued connection if you do not use threads.

        https://forum.qt.io/topic/113070/qt-code-of-conduct

        M 1 Reply Last reply 19 Nov 2021, 05:23
        3
        • J jsulm
          15 Nov 2021, 05:30

          @Mozzie said in Why the pointer of QVector always change when use QVector as parameter of signal?:

          Qt::QueuedConnection

          This is why: Qt::QueuedConnection is usually used for signals/slots across threads and in this case all parameters are copied. Do not use queued connection if you do not use threads.

          M Offline
          M Offline
          Mozzie
          wrote on 19 Nov 2021, 05:23 last edited by
          #4

          @jsulm
          I think this might not because the signal-slot, the pointer of the vector I am using is of the orignal QVector, no matter how much it was copied, the pointer of the orignal one should not be changed.
          And I found is I use QVector::data() or QVector::operator[int i], it will call the QVector::detach() function and the pointer is changed, but if I use QVector::constData(), it wouldn't call the QVector::detach() function and the result of QVector::constData() will not change.
          Do you know what is the difference between QVector::constData() and QVector::data()? I thought they are just have different return type before, it seems not right now. and why QVector::data() need to call QVector::detach()?

          Thank you.

          J 2 Replies Last reply 19 Nov 2021, 05:31
          0
          • M Mozzie
            19 Nov 2021, 05:23

            @jsulm
            I think this might not because the signal-slot, the pointer of the vector I am using is of the orignal QVector, no matter how much it was copied, the pointer of the orignal one should not be changed.
            And I found is I use QVector::data() or QVector::operator[int i], it will call the QVector::detach() function and the pointer is changed, but if I use QVector::constData(), it wouldn't call the QVector::detach() function and the result of QVector::constData() will not change.
            Do you know what is the difference between QVector::constData() and QVector::data()? I thought they are just have different return type before, it seems not right now. and why QVector::data() need to call QVector::detach()?

            Thank you.

            J Offline
            J Offline
            jsulm
            Lifetime Qt Champion
            wrote on 19 Nov 2021, 05:31 last edited by
            #5

            @Mozzie said in Why the pointer of QVector always change when use QVector as parameter of signal?:

            I think this might not because the signal-slot, the pointer of the vector I am using is of the orignal QVector

            Yes, it is. But only as long as you do not change any of the copies. Qt containers use https://doc.qt.io/qt-5/implicit-sharing.html
            As long as you do not change any of the QVector copy they all will point to the same data, so internal pointer will be the same.
            But as soon as you change one of the copy it will do detach (as you already mentioned) - the data will be copied for that vector and internal pointer will change.

            So, what I wrote before is correct.
            See https://woboq.com/blog/how-qt-signals-slots-work-part3-queuedconnection.html
            Especially "Copying the parameters".

            https://forum.qt.io/topic/113070/qt-code-of-conduct

            1 Reply Last reply
            3
            • M Mozzie
              19 Nov 2021, 05:23

              @jsulm
              I think this might not because the signal-slot, the pointer of the vector I am using is of the orignal QVector, no matter how much it was copied, the pointer of the orignal one should not be changed.
              And I found is I use QVector::data() or QVector::operator[int i], it will call the QVector::detach() function and the pointer is changed, but if I use QVector::constData(), it wouldn't call the QVector::detach() function and the result of QVector::constData() will not change.
              Do you know what is the difference between QVector::constData() and QVector::data()? I thought they are just have different return type before, it seems not right now. and why QVector::data() need to call QVector::detach()?

              Thank you.

              J Offline
              J Offline
              jsulm
              Lifetime Qt Champion
              wrote on 19 Nov 2021, 05:33 last edited by jsulm
              #6

              @Mozzie said in Why the pointer of QVector always change when use QVector as parameter of signal?:

              and why QVector::data() need to call QVector::detach()?

              I think only the non-const data() method will detach. Because you can change internal data using it, so it has to detach.
              If you don't want to detach use the const one: https://doc.qt.io/qt-5/qvector.html#data-1

              https://forum.qt.io/topic/113070/qt-code-of-conduct

              M 1 Reply Last reply 19 Nov 2021, 05:51
              3
              • J jsulm
                19 Nov 2021, 05:33

                @Mozzie said in Why the pointer of QVector always change when use QVector as parameter of signal?:

                and why QVector::data() need to call QVector::detach()?

                I think only the non-const data() method will detach. Because you can change internal data using it, so it has to detach.
                If you don't want to detach use the const one: https://doc.qt.io/qt-5/qvector.html#data-1

                M Offline
                M Offline
                Mozzie
                wrote on 19 Nov 2021, 05:51 last edited by
                #7

                @jsulm

                Thank you very much!

                1 Reply Last reply
                0

                1/7

                15 Nov 2021, 02:47

                • Login

                • Login or register to search.
                1 out of 7
                • First post
                  1/7
                  Last post
                0
                • Categories
                • Recent
                • Tags
                • Popular
                • Users
                • Groups
                • Search
                • Get Qt Extensions
                • Unsolved