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 511 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.
  • MozzieM Offline
    MozzieM Offline
    Mozzie
    wrote on 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

    jsulmJ 1 Reply Last reply
    0
    • B Offline
      B Offline
      Bonnie
      wrote on 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
      • MozzieM Mozzie

        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

        jsulmJ Offline
        jsulmJ Offline
        jsulm
        Lifetime Qt Champion
        wrote on 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

        MozzieM 1 Reply Last reply
        3
        • jsulmJ jsulm

          @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.

          MozzieM Offline
          MozzieM Offline
          Mozzie
          wrote on 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.

          jsulmJ 2 Replies Last reply
          0
          • MozzieM Mozzie

            @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.

            jsulmJ Offline
            jsulmJ Offline
            jsulm
            Lifetime Qt Champion
            wrote on 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
            • MozzieM Mozzie

              @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.

              jsulmJ Offline
              jsulmJ Offline
              jsulm
              Lifetime Qt Champion
              wrote on 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

              MozzieM 1 Reply Last reply
              3
              • jsulmJ jsulm

                @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

                MozzieM Offline
                MozzieM Offline
                Mozzie
                wrote on last edited by
                #7

                @jsulm

                Thank you very much!

                1 Reply Last reply
                0

                • Login

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