- "C++11/14/17 Features In VS 2015 RTM" - 2 Updates
- Understanding linked list copy constructor - 7 Updates
- Zeroing in the constructor - 2 Updates
- c++ programlama a-z butün konuların oldugu kitaplar sıfırdan baslayanlara ve kendisini gelistirmek isteyenler bu kaynak tam size göre - 1 Update
- returning const references to local variables - 5 Updates
- Ugly code to solve a combinatorial problem with an integer sum - 4 Updates
- About static const member in template class - 1 Update
Lynn McGuire <lmc@winsim.com>: Jun 22 05:05PM -0500 "C++11/14/17 Features In VS 2015 RTM" http://blogs.msdn.com/b/vcblog/archive/2015/06/19/c-11-14-17-features-in-vs-2015-rtm.aspx I wonder what happens to us folks who already have our own tuple methods and have ::std as the global namespace? i.e., "using namespace std;". Lynn |
Ian Collins <ian-news@hotmail.com>: Jun 23 10:19AM +1200 Lynn McGuire wrote: > I wonder what happens to us folks who already have our own tuple > methods and have ::std as the global namespace? > i.e., "using namespace std;". Valuable lesson learned! -- Ian Collins |
Paul <pepstein5@gmail.com>: Jun 22 01:01AM -0700 On Sunday, June 21, 2015 at 9:05:21 PM UTC+1, Paul N wrote: > > This function deletes all the nodes in the same way the destructor does. Also, I've read that you almost never need to invoke the destructor explicitly. If you shouldn't need to invoke the destructor explicitly, then surely you also shouldn't need to call a function which is an exact copy-paste of everything the destructor does. > Presumably when a list goes out of existence you want the memory used by its members to be freed. You may also want to clear the members of a list without destroying the list itself. So there is code to do this. It all seems perfectly normal. Except, that, if you're going to write the code for make_empty() it would seem sensible to just call this function in the destructor instead of writing the code again. > [snip actual code] Thanks. Sorry, I meant assignment, not the copy constructor. Paul |
Paul <pepstein5@gmail.com>: Jun 22 05:17AM -0700 On Sunday, June 21, 2015 at 9:05:21 PM UTC+1, Paul N wrote: > > This function deletes all the nodes in the same way the destructor does. Also, I've read that you almost never need to invoke the destructor explicitly. If you shouldn't need to invoke the destructor explicitly, then surely you also shouldn't need to call a function which is an exact copy-paste of everything the destructor does. > Presumably when a list goes out of existence you want the memory used by its members to be freed. You may also want to clear the members of a list without destroying the list itself. So there is code to do this. It all seems perfectly normal. Except, that, if you're going to write the code for make_empty() it would seem sensible to just call this function in the destructor instead of writing the code again. > [snip actual code] Thanks. make_empty() is called in assignment but not in the copy constructor. Is there a good reason to treat these two cases differently? Thank You. Paul |
Carlos Romero Brox <carlos.romero.brox@gmail.com>: Jun 22 07:45AM -0700 El lunes, 22 de junio de 2015, 14:18:13 (UTC+2), Paul escribió: > > [snip actual code] > Thanks. make_empty() is called in assignment but not in the copy constructor. Is there a good reason to treat these two cases differently? Thank You. > Paul I think copy ctor is used to initialize new objects (initialize a variable, pass an argument/return a value from a function) , there is no a previous value involved. Assignment operator replaces an "old" value with a "new" one and if there are resources associated to the old value, they should be freed |
Paul N <gw7rib@aol.com>: Jun 22 01:38PM -0700 On Monday, 22 June 2015 13:18:13 UTC+1, Paul wrote: > > Presumably when a list goes out of existence you want the memory used by its members to be freed. You may also want to clear the members of a list without destroying the list itself. So there is code to do this. It all seems perfectly normal. Except, that, if you're going to write the code for make_empty() it would seem sensible to just call this function in the destructor instead of writing the code again. > > [snip actual code] > Thanks. make_empty() is called in assignment but not in the copy constructor. Is there a good reason to treat these two cases differently? Thank You. If you do an assignment - say A = B where A and B are both lists - then you want to clear out the existing members of A, and then fill A up with copies of what is in list B. That's why you need the make_empty(). When you run a copy constuctor, the new list being created won't have any members yet and so there is no need to clear them out. |
Paul <pepstein5@gmail.com>: Jun 22 02:42PM -0700 On Monday, June 22, 2015 at 9:38:21 PM UTC+1, Paul N wrote: > > > Presumably when a list goes out of existence you want the memory used by its members to be freed. You may also want to clear the members of a list without destroying the list itself. So there is code to do this. It all seems perfectly normal. Except, that, if you're going to write the code for make_empty() it would seem sensible to just call this function in the destructor instead of writing the code again. > > > [snip actual code] > > Thanks. make_empty() is called in assignment but not in the copy constructor. Is there a good reason to treat these two cases differently? Thank You. Thanks for the explanations. Paul |
alf.p.steinbach@gmail.com: Jun 22 03:00PM -0700 On Monday, June 22, 2015 at 10:01:57 AM UTC+2, Paul wrote: > > On Sunday, 21 June 2015 17:02:09 UTC+1, Paul wrote: > > > The code below is copy-pasted from a university website. I don't understand the need for void make_empty() which is called in the copy constructor. > Thanks. Sorry, I meant assignment, not the copy constructor. When a copy assignment operator is called, the list is already initialized and may contain nodes. These have to be removed. This is work that the copy constructor doesn't have to do. Conversely, when the copy constructor is invoked there are no nodes to be removed, and the list is not yet initialized, so the copy constructor has to initialize various members. This is work that the copy assignment operator doesn't have to do. Copy assignment: clear first. Copy construction: initialize first. Still, there is no need to do that removal/clearing by duplicating code... The basic approach for a copy assignment operator is to express it in terms of copy construction, destruction and a no-throwing swap (like std::swap): class List { ... void swap_with( List& other ) noexcept { // Implementation of no-throwing swap // For example, std::swap( head, other.head ), etc. } auto operator=( List const& other ) -> List& { List the_copy( other ); // Invokes copy constructor swap_with( the_copy ); return *this; // Invokes destructor for old list } With this idiomatic approach code is not duplicated, just reused, and any exception occurring during the copying will leave the list in its original good state. Some people prefer to pass the argument by value, which means that the copy constructor is invoked at the point of call rather than in the assignment operator implementation itself, but at first sight it may be a little baffling: auto operator=( List the_copy ) -> List& { swap_with( the_copy ); return *this; // Invokes destructor for old list } Notes about the notation above: * Instead of a "swap_with" method, it's my impression that most people prefer a non-member "swap" function, perhaps expressed as an inline "friend" function. However, a non-member "swap" function can easily be expressed in terms of a "swap_with" method. The opposite, expressing a member function in terms of non-member function, is a bit unnatural to me. * Instead of the C++11 "auto" syntax for functions (a.k.a. trailing return type), most people still prefer the old C++03 function declaration syntax. I see no reason to use the old syntax except inertia, since the new syntax covers it all. The new syntax e.g. allows using class-local types in the return type without qualification, and it makes it easier for me to spot the function name. Cheers & hth., - Alf |
alf.p.steinbach@gmail.com: Jun 22 03:06PM -0700 > ... Sorry for the Quoted Printable encoding etc., that's Google Groups, not me. ;-) |
legalize+jeeves@mail.xmission.com (Richard): Jun 22 05:33PM [Please do not mail me a copy of your followup] Noob <root@127.0.0.1> spake the secret code >> Who are the 'we' who do keep saying that? The C++11 version is 4 years in >> the past and there are no big changes planned for next releases. >AFAICT, neither gcc nor VS fully support C++11 even today. C++11 support in VS is quite good from my perspective. <https://utahcpp.wordpress.com/2015/06/22/c111417-features-in-visual-studio-2015/> Microsoft has been improving their compiler rapidly in recent years. If you haven't looked at it in a while, you're missing a lot. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
JiiPee <no@notvalid.com>: Jun 22 09:34PM +0100 On 18/06/2015 17:09, Victor Bazarov wrote: > types, pointers included, when default-initialized (as opposed to > value-initialized), are left untouched. Memory is allocated for them, > but the contents of the memory is left unchanged. If I remember correctly globals are initialized by their "zero values", like int a; if global would be initialized to zero. Right? local variables are like you said... > changing it in the course of your calculations, then why bother > initializing it at all? Only initialize when you need particular > values to actually be there. so, would you initialize: int* p = nullptr; or just : int* p; ? I think it would be safer to put nullptr so that other code knows its not pointing to anywhere. |
yakup.2116@gmail.com: Jun 22 10:54AM -0700 arkadaslar simdide en çok kulanılan c++ programlama üzerine a-z e kitap paylasıyorum eger yeni ögrencekseniz bu arsıv size göre eger kendinizi gelistirecekseniz bu arsiv yine size göra a-z her konu var c++ üzerine indirmek için linkler http://bc.vc/As4ref veya http://bc.vc/F9Ggx6 virüs taraması yapmanız önerilir |
Paul <pepstein5@gmail.com>: Jun 22 01:14AM -0700 Is it ok to return const references to local variables. For example, the code below appears to run fine on my machine but it does give a warning. Thanks. Paul /** 2 * Return the maximum item in array a. 3 * Assumes a.size( ) > 0. 4 * Comparable objects must provide operator< and operator= 5 */ template <typename Comparable> const Comparable & findMax( const std::vector<Comparable> & a ) { int maxIndex = 0; int max = a[0]; for( int i = 1; i < a.size( ); ++i ) max = std::max(max, a[i]); return max; } int main() {std::vector<int> x = {23, 45, 67, 98, 3450, -10}; std::cout << std::endl << findMax(x) << std::endl; } |
Marcel Mueller <news.5.maazl@spamgourmet.org>: Jun 22 11:25AM +0200 On 22.06.15 10.14, Paul wrote: > max = std::max(max, a[i]); > return max; > } This is undefined behavior since max goes out of scope at the end of findMax and from that point you have a dangling reference. A smart compiler should warn you about this obvious fault. Marcel |
gwowen <gwowen@gmail.com>: Jun 22 07:38AM -0700 On Monday, June 22, 2015 at 9:14:39 AM UTC+1, Paul wrote: > Is it ok to return const references to local variables. For example, the code below appears to run fine on my machine but it does give a warning. No. Perhaps you're confusing it with the rule that says you can return a temporary, and bind it to a constant reference to extend its life? For this to apply, the return type is an object type, not a reference to an object. |
"Öö Tiib" <ootiib@hot.ee>: Jun 22 07:40AM -0700 On Monday, 22 June 2015 11:14:39 UTC+3, Paul wrote: > Is it ok to return const references to local variables. For example, > the code below appears to run fine on my machine but it does give a > warning. No. It is undefined behavior. It is good that it gives a warning because defective function whose behavior is undefined but that appears to run fine in simple test will (by Murphy's laws) blow everything up in most embarrassing and damaging for your reputation situation. > Thanks. Also there is other defect and it is inefficient. > /** 2 * Return the maximum item in array a. 3 * Assumes a.size( ) > 0. 4 * Comparable objects must provide operator< and operator= 5 */ Comparable must be of type that is or converts implicitly to 'int' (for example provides non-explicit 'operator int()') or ... > const Comparable & findMax( const std::vector<Comparable> & a ) { > int maxIndex = 0; > int max = a[0]; ... or above line is programming error. > {std::vector<int> x = {23, 45, 67, 98, 3450, -10}; > std::cout << std::endl << findMax(x) << std::endl; > } Inefficiency: your algorithm makes pointless copies of the elements of vector. There is 'std::max_element' that is more generic (works with any iteratable sequence) and significantly outperforms your algorithm on case the elements are cheap to compare but expensive to copy. I trust I already wrote that in other quite similar thread that you started. |
legalize+jeeves@mail.xmission.com (Richard): Jun 22 05:33PM [Please do not mail me a copy of your followup] Paul <pepstein5@gmail.com> spake the secret code >Is it ok to return const references to local variables. No. -- "The Direct3D Graphics Pipeline" free book <http://tinyurl.com/d3d-pipeline> The Computer Graphics Museum <http://computergraphicsmuseum.org> The Terminals Wiki <http://terminals.classiccmp.org> Legalize Adulthood! (my blog) <http://legalizeadulthood.wordpress.com> |
Luca Risolia <luca.risolia@linux-projects.org>: Jun 22 12:27PM +0200 > The specification was that the arithmetic signs shall be placed *between > the digits*. Right. Here is my algorithm then. Just to do something different, I tried not to use strings or sequence of chars. #include <iostream> #include <cstdint> #include <vector> #include <list> using Seq = std::vector<std::int32_t>; using List = std::list<Seq>; std::int32_t term(std::size_t p, std::size_t q) { return q > p ? 10 * term(p, q - 1) + q : p; } void solve_(int m, int n, std::int32_t r, std::int32_t s, Seq& terms, List& solutions) { for (int i = m; i <= n; ++i) { for (int f = -1; f <= 1; f += 2) { auto t = term(m, i) * f; if (t != -1) { terms.push_back(t); solve_(i + 1, n, r, s + t, terms, solutions); terms.pop_back(); } } } if (m > n && r == s) solutions.push_back(terms); } List solve(int m, int n, std::int32_t r) { Seq terms; terms.reserve(n - m + 1); List solutions; solve_(m, n, r, 0, terms, solutions); return solutions; } void print(const List& l) { for (const auto& s : l) { bool sign = false; for (const auto& t : s) { if (t > 0 && sign) std::cout << '+'; std::cout << t; sign = true; } std::cout << '\n'; } } int main() { auto solutions = solve(1, 9, 100); print(solutions); } --- // Output: 1+2+3-4+5+6+78+9 1+2+34-5+67-8+9 1+23-4+5+6+78-9 1+23-4+56+7+8+9 12-3-4+5-6+7+89 12+3-4+5+67+8+9 12+3+4+5-6-7+89 123-4-5-6-7+8-9 123+4-5+67-89 123-45-67+89 123+45-67+8-9 |
Luca Risolia <luca.risolia@linux-projects.org>: Jun 22 01:09PM +0200 On 22/06/2015 12:27, Luca Risolia wrote: > if (t != -1) { better: if (t > 0 || terms.size()) |
Juha Nieminen <nospam@thanks.invalid>: Jun 22 01:17PM >> if (t != -1) { > better: > if (t > 0 || terms.size()) if (t > 0 || !terms.empty()) --- news://freenews.netfront.net/ - complaints: news@netfront.net --- |
Luca Risolia <luca.risolia@linux-projects.org>: Jun 22 04:34PM +0200 On 19/06/2015 17:36, Stefan Ram wrote: > prints: > 1 2 3+4 5-6 7+8-9 Does not the problem say "put + or - *or nothing* between the numbers 1, 2, ..., 9"? I see some unneeded white spaces in your solutions. |
"Öö Tiib" <ootiib@hot.ee>: Jun 21 05:27PM -0700 On Sunday, 21 June 2015 19:19:17 UTC+3, Stefan Ram wrote: > seems to be that they sometimes used different wording for > the same thing, (possibly »user-defined« = »explicit« or so). > And this makes it even harder to read. One reason why the standard is hard to read is that it is meant as specification for writing C++ compilers and standard libraries. Specification and user's manual are usually different things. Other reason is that it is quite rapid voluntary work of many unrelated people on rather complex subject. The result of such work usually contains some controversies or inconsistencies. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment