Forum Replies Created

Viewing 15 posts - 301 through 315 (of 349 total)
  • Author
    Posts
  • in reply to: Throwing destructor #13051
    RainerRainer
    Keymaster
        Up
        0
        Down
        ::

        You got it right. I’m not sure if I like his throwing Close strategy. I strongly advise that a destructor should not throw.

        in reply to: Placement new #12818
        RainerRainer
        Keymaster
            Up
            0
            Down
            ::
            1. You are right, Account could be any class.
            2. Program start-up is essentially the time before main is executed. The following things happen perspective:
              1. C start-up code requires specific prerequisites
                1. Puts the interrupt vector table at an appropriate location
                2. Sets the stack pointer
                3. Static variables are initializes (.bss section)
                4. Const variables are stored in a separate section (.rodata section)
              2. C++ start-up code (additionally)
                1. Execution of static objects (constructor calls)
                2. iostreams initialized (cin, cout, cerr, and clog)

             

            in reply to: (Non)const local variable and move it or not #11509
            RainerRainer
            Keymaster
                Up
                0
                Down
                ::

                The first question you have to answer is: “What semantic does f1 and f2 have?”

                I already answered your question. A const lvalue reference is an in parameter and a non-const rvalue reference is an in and move from parameter.

                Regarding performance, both versions should be equivalent. Here is my simple rule of thumb for a parameter p:

                • The sizeof(p) <= 3 sizeof(int): copy
                • Otherwise: const lvalue reference

                 

                in reply to: (Non)const local variable and move it or not #11344
                RainerRainer
                Keymaster
                    Up
                    0
                    Down
                    ::

                    void f1(const MyClass& myClass) {  // in parameter
                        // ...
                    }
                    
                    void f2(MyClass&& myClass) {      // in and move from parameter
                        // ...
                    }
                    
                    ...
                    MyClass myClass;
                    f1(myClass);
                    f2(std::move(myClass));
                    f1(myClass); // myClass has valid but unspecified state
                    
                    • f1 uses an in parameter that you cannot change
                      • myClass is still usable by the caller
                    • f2 uses an in and move from parameter
                      • you enforce the caller to transfer the ownership of myClass into the function f2
                      • the lifetime of myClass is bound to the lifetime of f2
                      • myClass must after the call f2(std::move(myClass)) initialized
                    RainerRainer
                    Keymaster
                        Up
                        0
                        Down
                        ::

                        I made a complete program out of it:

                        #include <iostream>
                        #include <string>
                        
                        std::string getString() {
                            const std::string s;
                            return std::move(s); 
                        }
                        
                        int getInt() {
                            int x{10};
                            return std::move(x);  
                        }
                        
                        void f(const std::string &s){}
                        
                        
                        int main() {
                        
                            std::string s = getString();
                        
                            std::cout << getInt() << '\n';
                        
                            f(std::move(s));  
                        
                        }
                        

                        clang-tidy on Compiler Explorer gives the expected messages: https://godbolt.org/z/a575xebMa

                        in reply to: Moved object still pointing to the same address #10732
                        RainerRainer
                        Keymaster
                            Up
                            0
                            Down
                            ::

                            It makes no sense to apply std::move on a pointer. strView.data() returns a pointer to the underlying character array.

                            => Don’t use std::move(strView.data()); (This holds for a std::string and a std::string_view)

                            in reply to: GitHub Exercise and Solution .cpp is same #10344
                            RainerRainer
                            Keymaster
                                Up
                                0
                                Down
                                ::

                                Hi Mounir,

                                I don’t get you. The exercise folder should have examples and sometimes the starting points for the exercises. The solution’s folder should only have the solutions for the exercises. I checked a few files, and they are as intended,

                                Rainer

                                in reply to: User-defined move Ctor #10342
                                RainerRainer
                                Keymaster
                                    Up
                                    0
                                    Down
                                    ::

                                    Option 2 is in general a bad idea.

                                    You cannot be sure that the compiler generated copy constructor (= default) have the same semantic as your user-defined move constructor. For example, your use-defined move constructor sets other._data = nullptr, but the compiler generated move constructor not.

                                    MyData( MyData&& other ) noexcept : _i( other._i ), _data( other._data ) {
                                        std::cout << "I am move Ctor" << std::endl;
                                        other._i = 0;
                                        other._data = nullptr;
                                    };
                                    
                                    // MyData( MyData&& other ) = default could essentially do the following
                                    
                                    MyData( MyData&& other ) noexcept : _i( other._i ), _data( other._data ) {}
                                    

                                    Now, a user-defined destructor could terribly fail due to double delete.

                                    ~MyData() noexcept {
                                        if (_data != nullptr) delete[] data_;
                                    }
                                    

                                    Here is my contrived example: https://godbolt.org/z/Yn63x1chz

                                    Either =default all of them or define all of them.

                                    in reply to: When to use std::move? #10187
                                    RainerRainer
                                    Keymaster
                                        Up
                                        0
                                        Down
                                        ::

                                        I’m not sure if this rule of thumb always apply. Meaning, I may fix them later.

                                        • Use std::move(lval) when you want to transfer the ownership of an object. In this case, lval is a lvalue.
                                        • Don’t use std::move(rval), when rval is already an rvalue such as in your examples (temporary, and return statement). You can only suppress move semantics by using std::move.
                                        in reply to: Self-assignemt check for move assignment operator #10177
                                        RainerRainer
                                        Keymaster
                                            Up
                                            0
                                            Down
                                            ::

                                            Let me directly answer your questions:

                                            Foo& Foo::operator=(Foo&& a) noexcept {
                                                s = std::move(a.s);
                                                i = a.i;
                                                return *this;
                                            }
                                            
                                            1. After applying the move constructor, a is in valid but unspecified state. I base my implementation on the move constructor of std::string, and the copy constructor of
                                            2. This is a very controversial discussion. Here is the reasoning of Howard Hinnard, who design move semantics:
                                              • When an object binds to an rvalue reference it is one of two things:
                                                • A temporary.
                                                • An object the caller wants you to believe is a temporary. (e.g.: using std::move)
                                              • After the move assignment operation, the moved-from object must be in a valid but unspecified state. This means,  that the check for self-assignment adds no value. It only cost a bit. Consequentially, I don’t do it.

                                            Here is an additional point, you should keep in mind, when you apply the move assignment operator that is often forgotten. You are already the owner of some resources. Consequentially, you have to delete your existing data:

                                            Foo& Foo::operator=(Foo&& a) noexcept {
                                                1. Delete existing data
                                                2. Move state from other
                                                3. Set state from other in a "valid but unspecified state"
                                            }
                                            

                                            For the move constructor, only steps 2 and 3 are necessary.

                                            in reply to: Moved object still pointing to the same address #10175
                                            RainerRainer
                                            Keymaster
                                                Up
                                                0
                                                Down
                                                ::

                                                You have to distinguish the C++ string and the C-string, the C++ string owns.

                                                #include <iostream>
                                                #include <string>
                                                
                                                int main() {
                                                
                                                    std::string str1{ "ABCDEF" };
                                                    std::string str2;
                                                  
                                                    std::cout << "str1: " << str1 << '\n'; 
                                                    std::cout << "&str1: " << &str1 << '\n';
                                                    std::cout << "str1.size(): " << str1.size() << '\n'; 
                                                    std::cout << "str1.data(): " << str1.data() << '\n';
                                                
                                                    std::cout << "\n\n";
                                                    str2 = std::move(str1);
                                                    std::cout << "str1: " << str1 << '\n'; 
                                                    std::cout << "&str1: " << &str1 << '\n';
                                                    std::cout << "str1.size(): " << str1.size() << '\n'; 
                                                    std::cout << "str1.data(): " << str1.data() << '\n';
                                                
                                                }
                                                
                                                • C++ string: str1
                                                • C string, that str1 owns: str1.data()

                                                Here is the corresponding program: https://godbolt.org/z/4zEhnGc8a

                                                in reply to: Sale on C++ Concurrency in Action #10135
                                                RainerRainer
                                                Keymaster
                                                    Up
                                                    0
                                                    Down
                                                    ::

                                                    This book is the definite guide for concurrency in C++. This means, it’s very accurate and very challenging, in particular, when you read the parts about atomics and lock-free data structures.

                                                    C++20 brought significant additions to concurrency.

                                                    • std::atomic_ref
                                                    • atomic shared pointer
                                                    • std::atomic<floating point values>
                                                    • Waiting on atomics
                                                    • Semaphores, latches, and barriers
                                                    • std::jthread
                                                    • Coroutines (workflow related)

                                                    Here is an overview of the post I have published about C++20 including concurrency.

                                                     

                                                     

                                                    in reply to: Allocating memory on the heap vs the stack #10124
                                                    RainerRainer
                                                    Keymaster
                                                        Up
                                                        0
                                                        Down
                                                        ::

                                                        Here is the short answer. The longer will follow in week 7 (memory) and week 18 (smart pointers)

                                                        • The size of the stack is limited (roughly 2 megabyte). Heap has typically a few gigabytes. Compare the size of the std::size and the std::vector in my post “Copy versus Move Semantics: A few Numbers”
                                                        • Your object’s lifetime should not be bound to a local scope (e.g.: function). A typical example is a factory. A factory creates objects and returns them to the caller.

                                                        When you need new and delete, here is the rule of thumb: nnn (no naked new)  => Your new call should be performed inside a guard like std::unique_ptr.

                                                        in reply to: Non-movable types #10123
                                                        RainerRainer
                                                        Keymaster
                                                            Up
                                                            0
                                                            Down
                                                            ::

                                                            Essentially, all types used in concurrency are non-movable. Only one exception comes into my mind: std::shared_future.

                                                            in reply to: constexpr if statement #10097
                                                            RainerRainer
                                                            Keymaster
                                                                Up
                                                                0
                                                                Down
                                                                ::

                                                                Honestly, this example is too complicated at that point in time. I need to explain a few additional features first:

                                                                Your example is a nice example, when I would make a deep dive into programming at compile time or designs patterns with modern C++. I will do both in the future.

                                                                Here are the essential posts you can read:

                                                                I don’t see the point of your question: ” Maybe discuss the std::variant’s std::visit() call, how the if branches are created in compile time, while the objects are in runtime…” This is always happening. An if or case statement is created at compile time, but used at run time. In case of a constexpr if, you only created it when the condition holds.

                                                                 

                                                              Viewing 15 posts - 301 through 315 (of 349 total)