CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 15 of 15
  1. #1
    Join Date
    Aug 2019
    Posts
    72

    array of objects

    Hi,
    When using vector to create array of object, the destructor gets called right after the constructor, but when i use new it works OK.
    std::vector<MyClass> myobj(numofobjects, MyClass());

    Code:
    class MyClass {
      Myclass()
      {
      }
     virtual ~Myclass()
      {
      }

  2. #2
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: array of objects

    Quote Originally Posted by @EE@ View Post
    Hi,
    When using vector to create array of object, the destructor gets called right after the constructor, but when i use new it works OK.
    std::vector<MyClass> myobj(numofobjects, MyClass());

    Code:
    class MyClass {
      Myclass()
      {
      }
     virtual ~Myclass()
      {
      }
    What does (in this context) mean "works OK"?
    And when it would be assumed to be "not OK"?
    Victor Nijegorodov

  3. #3
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: array of objects

    Post a complete compilable test program that shows the issue.
    Last edited by 2kaud; October 7th, 2021 at 03:21 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  4. #4
    Join Date
    Aug 2019
    Posts
    72

    Re: array of objects

    when using std::vector<MyClass> myobj(numofobjects, MyClass()); to create arary of objects , Myclass() destructor get called after its constructor and execution stops. with new it does not occur and execution continues.

    Code:
    class MyClass {
    
    public:
    
      Myclass()
      {
          myobj2 = new MyClass2();
      }
     virtual ~Myclass()
      {
    delete myobj2;
    myobj2 = NULL;
      }
     
      MyClass2 * myobj2;

  5. #5
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: array of objects

    Quote Originally Posted by @EE@ View Post
    when using std::vector<MyClass> myobj(numofobjects, MyClass()); to create arary of objects...
    In your sample code there is no any array/vector of MyClass.
    Victor Nijegorodov

  6. #6
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: array of objects

    As I said above, post a complete compilable test program that shows the issue.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  7. #7
    Join Date
    Aug 2019
    Posts
    72

    Re: array of objects

    when program starts , after the first constructor call. ~MyClass() destructor is immediately called

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>      
    using namespace std;
    
    class MyClass {
    	
    public:
    	MyClass() 
    	{ 
    		arr = new int[10];
    		cout << count++ << endl;
    	}
    	virtual ~MyClass() 
    	{ 
    		cout << "exiting!" << endl; 
    		delete[] arr; 
    		arr = NULL;  
    	}
    	int getarrElem(int i) 
    	{ 
    		return arr[i]; 
    	}
    	int *arr;
    	int count = 0;
    };
    
    int main()
    {
    	std::vector<MyClass> obj(10, MyClass());
    	cout << obj[1].getarrElem(5);
    	return 0;
    }

  8. #8
    VictorN's Avatar
    VictorN is offline Super Moderator Power Poster
    Join Date
    Jan 2003
    Location
    Hanover Germany
    Posts
    20,396

    Re: array of objects

    Just debug your code step-by-step, also stepping in the std::vector ctor!
    Victor Nijegorodov

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: array of objects

    when program starts , after the first constructor call. ~MyClass() destructor is immediately called
    Correct. This is how the code should work.

    This behaviour is caused by the call to vector constructor. You are passing 10 and MyClass() as arguments. This means create 10 elements and initialise each element to MyClass(). MyClass() invokes the default constructor, constructs a temporary object which is passed to the vector constructor and then invokes the MyClass destructor when the temp object goes out of scope. Thus the vector is initialised with 10 invalid objects.

    You don't need to use MyClass() in the vector constructor. if you don't then the vector constructor will call the default constructor for MyClass each time - which is what is wanted here.

    Consider:

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    using namespace std;
    
    constexpr size_t noobjs {10};
    constexpr size_t noelems {10};
    
    class MyClass {
    public:
    	MyClass() : arr(new int[noelems] {1,2,3,4,5,6,7,8,9,10}) {
    		cout << count++ << endl;
    	}
    
    	~MyClass() {
    		cout << "exiting!" << endl;
    		delete[] arr;
    	}
    
    	int getarrElem(int i) {
    		return arr[i];
    	}
    
    	int* arr {};
    	inline static int count {};
    };
    
    int main()
    {
    	std::vector<MyClass> obj(noobjs);
    
    	cout << obj[1].getarrElem(5) << '\n';
    }
    which displays:

    Code:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    6
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Aug 2019
    Posts
    72

    Re: array of objects

    I added threads to my array of objects. It crashes when main exits. Also, static member gives an error. not sure how to handle these two cases?.

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>   
    #include <thread>
    #include <windows.h>
    using namespace std;
    
    constexpr size_t noobjs{ 10 };
    constexpr size_t noelems{ 10 };
    
    class MyClass {
    public:
    	MyClass() : arr(new int[noelems] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {
    		cout << count++ << endl;
    	}
    
    	~MyClass() {
    		cout << "exiting!" << endl;
    		if (arr != NULL)
    		{
    			delete[] arr; //crashes when main exits, due to obj destrustor being called?.
    		}
    	}
    
    	void dosomthing() {
    		//do something
    	}
    
    	int* arr = NULL;
    	//static int count; //Error	LNK2001	unresolved external symbol "public: static int MyClass::count"
    	int count = 0;
    };
    
    int main()
    {
    	int t = 10;
    	std::vector<MyClass> obj(noobjs);
    
    	vector<std::thread> myThs(t);
    
    	for (int i = 0; i < t; i++) {
    		myThs[i] = std::thread(&MyClass::dosomthing, obj[i]);
    		SetThreadPriority(myThs[i].native_handle(), THREAD_PRIORITY_HIGHEST);
    	}
    
    	//Join the threads with the main thread
    	for (int i = 0; i < t; ++i)
    	{
    		myThs[i].join();
    	}
    
    }

  11. #11
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: array of objects

    Since C++17, you use inline with static. See my code above.

    However, the problem is with the std::thread(). You need to pass obj[i] by address - not by value. The way you're doing it means that you get duplicate destructors called - hence the crash. Passing by value means that a copy is done by the class copy constructor. However as one isn't defined, the default one is used. This does a shallow memory copy rather than a deep copy (ie just copies the memory pointer without first allocating memory and copying). Then the destructor of the copied object is called when it goes out of scope which frees the memory - which is the original memory as a shallow copy was done. Then at the end of the program the destructor is called for the created objects. But the memory has already been freed by the destructor of the copied object so delete tries to delete already deleted memory and hence the crash.

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <thread>
    //#include <windows.h>
    
    constexpr size_t noobjs {10};
    constexpr size_t noelems {10};
    
    class MyClass {
    public:
    	MyClass() : arr(new int[noelems] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {
    		std::cout << count++ << '\n';
    	}
    
    	~MyClass() {
    		std::cout << "exiting!\n";
    		delete[] arr;
    	}
    
    	void dosomthing() {
    		std::cout << "do\n";
    		//do something
    	}
    
    	int* arr {};
    	inline static int count {};
    };
    
    int main()
    {
    	std::vector<MyClass> obj(noobjs);
    	std::vector<std::thread> myThs(noobjs);
    
    	for (int t = 0; t < noobjs; ++t) {
    		myThs[t] = std::thread(&MyClass::dosomthing, &obj[t]);
    		//SetThreadPriority(myThs[i].native_handle(), THREAD_PRIORITY_HIGHEST);
    	}
    
    	//Join the threads with the main thread
    	for (int i = 0; i < noobjs; ++i)
    		myThs[i].join();
    }
    Code:
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    do
    do
    do
    do
    do
    do
    do
    do
    do
    do
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    exiting!
    Last edited by 2kaud; October 9th, 2021 at 01:12 PM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  12. #12
    Join Date
    Feb 2017
    Posts
    677

    Re: array of objects

    Quote Originally Posted by @EE@ View Post
    I added threads to my array of objects. It crashes when main exits.
    The problem is that MyClass is not copyable because of the heap-allocated array held by the arr-pointer. And, as mentioned in #11, it gets copied here (underlined),

    Code:
    myThs[i] = std::thread(&MyClass::dosomthing, obj[i]);
    When a MyClass object gets copied, the default copy constructor produces a shallow copy. It means the original object and all copies made from it will have identical arr-pointers pointing at the same array on the heap. When one of these objects gets destructed, the arr-pointers of all remaining objects become stale. And when yet another gets destructed, the program crashes. One way to avoid this is to make sure MyClass objects never get copied. Another way is to make MyClass copyable, for example, by adding a copy constructor that produces a deep copy, or by replacing the heap-allocated array with a statically allocated array, either a C-array as before or preferably an std::array.
    Last edited by wolle; October 11th, 2021 at 02:00 AM.

  13. #13
    Join Date
    Aug 2019
    Posts
    72

    Re: array of objects

    Is there a reason why the SetThreadPriority is removed by 2Kaud?. Maybe it is not genuine c++?? may actually run faster without it??.
    is the "writetoFile" thread safe?. I like to make sure the each thread executes "writetoFile" and creates the file. Kept the "GetStrCount" and "WriteToFile" separate on purpose.
    inline static int count{}; //this line gives error in v14.0 platform

    Code:
    #include <iostream>
    #include <vector>
    #include <algorithm>   
    #include <thread>
    #include <fstream>
    using namespace std;
    
    //#include <windows.h>
    
    constexpr size_t noobjs{ 10 };
    constexpr size_t noelems{ 10 };
    
    class MyClass {
    public:
    	MyClass() : arr(new int[noelems] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}) {
    		//std::cout << count++ << '\n';
    	}
    
    	~MyClass() {
    		std::cout << "exiting!\n";
    		delete[] arr;
    	}
    
    	void dosomthing() {
    		std::cout << "do\n";
    		writetoFile("Hello World  ", input);
    	}
    
    	int* arr{};
    	//inline static int count{};  //this line gives error in visual studio v14.0 platform
    
    	void setinput(int inp)
    	{
    		input = inp;
    	}
    
    	inline string GetStrCount(int inp) {
    		sprintf(buf, "_%d", inp);
    		return string(buf);
    	};
    	inline void writetoFile(string myStr, int digit) {
    		buf[0] = '\0';
    		sprintf(buf, ".\\myfile_%s.txt", GetStrCount(digit).c_str());
    		ofstream ofs(buf, std::ios_base::out | std::ios_base::app);
    		ofs << (myStr+GetCount(digit)).c_str() <<endl;
    		ofs.close();
    		ofs.clear();
    	}
    
    	char buf[100];
    	int input;
    };
    
    int main()
    {
    	std::vector<MyClass> obj(noobjs);
    	std::vector<std::thread> myThs(noobjs);
    
    	for (int t = 0; t < noobjs; ++t)
    	{
    		obj[t].setinput(t);
    	}
    
    	for (int t = 0; t < noobjs; ++t) {
    		myThs[t] = std::thread(&MyClass::dosomthing, &obj[t]);
    		//SetThreadPriority(myThs[i].native_handle(), THREAD_PRIORITY_HIGHEST);
    	}
    
    	//Join the threads with the main thread
    	for (int i = 0; i < noobjs; ++i)
    		myThs[i].join();
    }
    Last edited by @EE@; October 10th, 2021 at 09:37 PM.

  14. #14
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,822

    Re: array of objects

    @EE

    I commented out SetThreadPriority() just for my testing - as it wasn't part of the issue.

    inline static int count{}; //this line gives error in v14.0 platform - You need to update your compiler to at least C++17.

    is the "writetoFile" thread safe? Yes - assuming that each call refers to a different file and a diffeerent class instantiation.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  15. #15
    Join Date
    Aug 2019
    Posts
    72

    Re: array of objects

    thank you 2kaud and others.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured