Thread: How can I prevent the duplication of stdlib.h in main.cpp?

  1. #1
    Registered User
    Join Date
    Oct 2019
    Posts
    43

    How can I prevent the duplication of stdlib.h in main.cpp?

    How can I prevent the duplication of stdlib.h in main.cpp?


    Code:
    // AllocateVector.h
    #ifndef ALLOCATEVECTOR_H
    #define ALLOCATEVECTOR_H
    #include <stdlib.h>
    
    
    template <class dataType>
    int allocateData1DbyMalloc(dataType*& data1D, unsigned int nRow) {
    	data1D = (dataType*)malloc(nRow * sizeof(dataType)); // sizeof(type1));
    	return (data1D != NULL) ? EXIT_SUCCESS : EXIT_FAILURE;
    }
    #endif
    
    
    // AllocateMatrix.h
    #ifndef ALLOCATEMATRIX_H
    #define ALLOCATEMATRIX_H
    #include <stdlib.h>
    
    
    int allocateData2DbyMalloc(dataType**& data2D, unsigned int nRow, unsigned int nColumn) {
    	data2D = (dataType * *)malloc(nRow * sizeof(dataType*)); // calloc(nRow, sizeof(type1*));
    	if (data2D == NULL) {
    		return EXIT_FAILURE;
    	}
    
    
    	// Now point each row to an array of nColumn type1 objects
    	for (unsigned int i = 0; i < nColumn; ++i) {
    		data2D[i] = (dataType*)malloc(nColumn * sizeof(dataType)); //calloc(nColumn, sizeof(type1));
    		if (data2D[i] == NULL) {
    			return EXIT_FAILURE;
    		}
    	}
    	return EXIT_SUCCESS;
    }
    #endif
    
    
    //main.cpp
    #include "AllocateVector.h"
    #include "AllocateMatrix.h"
    int main()
    {
    
    
    	return 0;
    }

  2. #2
    Guest
    Guest
    You should post this in the C++ forum, as this isn't C.

    What the error message do you get? Also, you're missing a template declaration on line #20, in case that wasn't just lost in the copy/paste.

  3. #3
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    * moved to C++ programming forum *

    Quote Originally Posted by Shafiul
    How can I prevent the duplication of stdlib.h in main.cpp?
    Duplicate inclusions of standard headers are perfectly fine. It's why you write your own header inclusion guards, after all: so it's perfectly fine should one of your own headers end up included more than once in a translation unit.

    EDIT:
    Ugh, and you're still not paying attention to C++ best practices. Here's one by Stroustrup and Sutter: R.10: Avoid malloc() and free(). Stroustrup is the designer and original implementor of C++; Sutter has been a prominent member of the C++ standards committee for years.

    Here's an (uncompiled, untested) example that's closer to how we would do it in modern C++:
    Code:
    #ifndef ALLOCATEVECTOR_H
    #define ALLOCATEVECTOR_H
    // AllocateVector.h
    
    #include <vector>
    
    template<typename T>
    std::vector<T> createData1D(std::size_t nRow) {
        return std::vector<T>(nRow);
    }
    
    #endif
    
    
    #ifndef ALLOCATEMATRIX_H
    #define ALLOCATEMATRIX_H
    // AllocateMatrix.h
    
    #include <vector>
    
    template<typename T>
    std::vector<std::vector<T>> createData2D(std::size_t nRow, std::size_t nColumn) {
        return std::vector<std::vector<T>>(nRow, std::vector<T>(nColumn));
    }
    
    template<typename T>
    class Data2D {
    public:
        Data2D(std::size_t nRow, std::size_t nColumn) : nRow(nRow), nColumn(nColumn), data(nRow * nColumn) {}
    
        T& operator()(std::size_t row, std::size_t column) {
            return data[row * nColumn + column];
        }
    
        const T& operator()(std::size_t row, std::size_t column) const {
            return data[row * nColumn + column];
        }
    private:
        std::size_t nRow;
        std::size_t nColumn
        std::vector<T> data;
    };
    
    #endif
    
    
    //main.cpp
    #include <iostream>
    #include "AllocateVector.h"
    #include "AllocateMatrix.h"
    
    int main()
    {
        auto data1D = createData1D<int>(100);
        std::cout << data1D[0] << std::endl;
    
        auto data2Dnested = createData2D<int>(100, 200);
        std::cout << data2Dnested[10][20] << std::endl;
    
        auto data2D = Data2D<int>(100, 200);
        std::cout << data2D(10, 20) << std::endl;
    
        return 0;
    }
    Last edited by laserlight; 10-30-2019 at 06:53 PM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Oct 2019
    Posts
    43
    Dear Laserlight,
    Thanks for your explanation, nice of you though. your code looks very impressive and modern. I do feel, I still may need sometime to go through c++ from c. But always nice to share my idea with such a people. Thanks in advance.

  6. #6
    Registered User
    Join Date
    Oct 2019
    Posts
    43
    Dear Laserlight,
    A quick question. How do you define ex-tern template function inside of AllocateVector.h for createData1D() to avoid the recompilation of the same function. Because AllocateVector.h can be included into different different source (.cpp) files.
    Code:
     
     // AllocateVector.h//
    #ifndef ALLOCATEVECTOR_H
    #define ALLOCATEVECTOR_H
    
    #include <vector>
    
    template<typename T>
    std::vector<T> createData1D(std::size_t nRow) {
        return std::vector<T>(nRow);
    }
    
    #endif
    Moreover the data type of the vector<T> createData1D() can be change at different different run. For example it can be createData1D<int>(100). It also can be createData1D<double>(100). If you have any idea please share.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Shafiul
    How do you define ex-tern template function inside of AllocateVector.h for createData1D() to avoid the recompilation of the same function. Because AllocateVector.h can be included into different different source (.cpp)
    You could use an extern template, but I wouldn't bother: these function templates are good candidates for inlining.

    Quote Originally Posted by Shafiul
    Moreover the data type of the vector<T> createData1D() can be change at different different run. For example it can be createData1D<int>(100). It also can be createData1D<double>(100). If you have any idea please share.
    You need to go into greater detail as to what you have in mind. It could be that you want to use a variant type instead (e.g., the new std::variant), or maybe not.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    Oct 2019
    Posts
    43
    Dear Laserlight,
    I would like to share a bit details idea on my implementation. For instance, I have a data source in file, i have a matrix.cpp and vector.cpp. actually matrix (2d array) and vector (1d array) will take their data from the data source file. Afterwards, matrix and vector array will be passed to different different algorithm for solution. Each algorithm has their own .cpp file where i need to include AllocateVector.h and AllocateMatrix.h. in such a case, imagine, the content of the AllocateVector.h will be compiled in each .cpp file. I am just a bit worry that it can increase the compilation time.

  9. #9
    Registered User
    Join Date
    Oct 2019
    Posts
    43
    Hi Laserlight,
    I performed a simple test to compare the performance speed on malloc() and vector<>. I would like to share with you. The taste case was on a 2D array with 1000x1000 with the number of iteration of 1000. The malloc array took 91.3s where as the vector array took 131.5 s. I wonder about the correct implementation on code for the comparison on the those two array. In the real time simulation of heat transfer, the number of iteration can be around 10000000 for a 2D (1000x1000) matrix. The comparison code is as follows.

    Code:
    //main.cpp
    #include <iostream>
    #include <vector>
    #include <ctime>
    #include <stdlib.h>
    
    
    template <class dataType>
    int allocateData2DbyMalloc(dataType**& data2D, unsigned int nRow, unsigned int nColumn) {
    	data2D = (dataType * *)malloc(nRow * sizeof(dataType*)); // calloc(nRow, sizeof(type1*));
    	if (data2D == NULL) {
    		return EXIT_FAILURE;
    	}
    
    
    	// Now point each row to an array of nColumn type1 objects
    	for (unsigned int i = 0; i < nColumn; ++i) {
    		data2D[i] = (dataType*)malloc(nColumn * sizeof(dataType)); //calloc(nColumn, sizeof(type1));
    		if (data2D[i] == NULL) {
    			return EXIT_FAILURE;
    		}
    	}
    	return EXIT_SUCCESS;
    }
    
    
    template <class dataType>
    void deAllocateData2DbyFree(dataType** data2D, unsigned int numberOfRow) {
    	for (unsigned int row = 0; row < numberOfRow; row++)
    		free(data2D[row]);
    	free(data2D);
    }
    
    
    
    
    template<typename T>
    std::vector<std::vector<T>> createData2D(std::size_t nRow, std::size_t nColumn) {
    	return std::vector<std::vector<T>>(nRow, std::vector<T>(nColumn));
    }
    
    
    int main()
    {
    	int matDim = 1000;
    	int matDimX = matDim;
    	int matDimY = matDim;
    	int itarationNumber = 1000;
    	double **matrix2D = nullptr;
    
    
    	std::clock_t start;
    	double duration;
    
    
    //-------------------------------- For 2DMallocArray it took 91.3s ----------------------
    	start = std::clock();
    	for (int i = 0; i < itarationNumber; i++)
    	{
    		allocateData2DbyMalloc(matrix2D, matDimX, matDimY);
    		if (matrix2D == nullptr) {
    			std::cout << "Error in 2D Array" << std::endl;
    			exit(0);
    		}
    
    
    		for (int row = 0; row < matDimX; row++)
    		{
    			for (int col = 0; col < matDimY; col++)
    			{
    				int lowest = 1, highest = 10;
    				int range = (highest - lowest) + 1;
    				double random_number = lowest + (range * (rand() / (RAND_MAX + 1.0)));
    				matrix2D[row][col] = random_number;
    			}
    		}
    
    
    		if (matrix2D)
    		{
    			deAllocateData2DbyFree(matrix2D, matDimX);
    			matrix2D = nullptr;
    		}
    	}
    	duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
    	std::cout << "printf: " << duration << '\n';
    
    
    //-------------------------------- For 2DVectorarray it took 131.5s ---------------------------------------
    /*	start = std::clock();
    	for (int i = 0; i < matDim; i++)
    	{
    		auto data2Dnested = createData2D<int>(matDim, matDim);
    		for (int row = 0; row < matDimX; row++)
    		{
    			for (int col = 0; col < matDimY; col++)
    			{
    				int lowest = 1, highest = 10;
    				int range = (highest - lowest) + 1;
    				double random_number = lowest + (range * (rand() / (RAND_MAX + 1.0)));
    				data2Dnested[row][col] = random_number;
    			}
    		}
    	}
    	duration = (std::clock() - start) / (double)CLOCKS_PER_SEC;
    	std::cout << "printf: " << duration << '\n';*/
    //------------------------------- End --------------------------------------------
    	return 0;
    }

  10. #10
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Your code has an error, although it doesn't show up in your example since you are creating a square matrix.
    Code:
        // In allocateData2DbyMalloc, this
        for (unsigned int i = 0; i < nColumn; ++i) {
        // should be this
        for (unsigned int i = 0; i < nRow; ++i) {
    You can speed it up a lot by mallocing the data block as one chunk, then setting the pointers, like this:
    Code:
        // allocate row pointers
        data2D = malloc(nRow * sizeof *data2D);
        // allocate entire data block
        data2D[0] = malloc(nRow * nColumn * sizeof **data2D);
        // point row pointers into data block
        for (unsigned i = 1; i < nRow; ++i)
            data2D[i] = data2D[i - 1] + nColumn;
    A little inaccuracy saves tons of explanation. - H.H. Munro

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Shafiul
    in such a case, imagine, the content of the AllocateVector.h will be compiled in each .cpp file. I am just a bit worry that it can increase the compilation time.
    This is a rare case of hearing someone indulge in premature optimisation for compile time, even more strangely when the compiler might be able to optimise for runtime. I'd say that this should be treated like the usual for non-trivial optimisation: measure first, then optimise, i.e., try compiling your actual code, and if it turns out to take so long that it becomes a pain point, look into extern templates or specialising for your common types.

    Quote Originally Posted by Shafiul
    I performed a simple test to compare the performance speed on malloc() and vector<>. I would like to share with you. The taste case was on a 2D array with 1000x1000 with the number of iteration of 1000. The malloc array took 91.3s where as the vector array took 131.5 s. I wonder about the correct implementation on code for the comparison on the those two array.
    You're right to suspect that the two code snippets aren't doing the same thing: the vector does default initialisation, whereas malloc doesn't. One way to avoid this is to reserve the final capacity, then push_back or emplace_back the new elements in the loop.

    More importantly though, did you compile with optimisations turned on, range checking turned off, in some kind of release mode (e.g., NDEBUG defined)?

    Quote Originally Posted by Shafiul
    In the real time simulation of heat transfer, the number of iteration can be around 10000000 for a 2D (1000x1000) matrix.
    Will you be spending all those iterations doing nothing but providing initial values? Seems pretty unlikely to me.

    Furthermore, john.c is right to say that if you're concerned about efficiency, you wouldn't be allocating in a loop like that when you want a rectangular 2D array for which you already know the dimensions. You're effectively treating it like a jagged 2D array, which is why I demonstrated the equivalent with a vector of vectors... but each vector in a vector of vectors stores its own size (and capacity), which is essential for a jagged 2D array, but redundant for a rectangular 2D array. If you look at my code in post #3 again, you'll see the Data2D class that does a single allocation, then computes the row offsets to compute the index for each element denoted by row and column. You can precompute these row offsets instead by sacrificing a bit more space for pointers to the start of each row, which is what john.c's example does (though with malloc).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > The taste case was on a 2D array with 1000x1000 with the number of iteration of 1000.
    > The malloc array took 91.3s where as the vector array took 131.5 s
    Right, and having allocated a 1000x1000 array, did you time how long it would take to fill the each with 1000000 values of meaningful data, and do some calculations.

    You allocate these things to do some work, and that allocation time is going to be completely INSIGNIFICANT compared to the overall time it takes to do the work.
    You're worrying about 40mS between the two, when you've no idea about the minutes or hours it's going to take to get through all that data.

    Show us your actual problem, not your attempts to micro-optimise one facet of it.
    The XY Problem
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. stdlib.h in C
    By rm82co in forum C++ Programming
    Replies: 3
    Last Post: 06-07-2019, 09:39 PM
  2. stdlib help!!
    By clique in forum C Programming
    Replies: 5
    Last Post: 10-08-2008, 10:57 AM
  3. Removing Duplication from Matrix Rows.
    By RP319 in forum C++ Programming
    Replies: 3
    Last Post: 04-03-2006, 05:40 PM
  4. Replies: 11
    Last Post: 03-22-2003, 01:50 PM
  5. Replies: 5
    Last Post: 02-05-2003, 02:52 PM

Tags for this Thread