Isn't the Const Modifier Here Unnecessary

Isn't the const modifier here unnecessary?

The point is that for class types (but not for builtin types), a = b is just a shorthand to a.operator=(b), where operator= is a member function. And member functions can be called on rvalues such (a * b) created by Rational::operator*. To enforce similar semantics as for builtin rvalues ("do as the ints do") some authors (Meyers including) recommended in C++98 to return by const-rvalue for classes with such operators.

However, in C++11 returning by const-rvalue is a bad idea as it will inhibit move semantics because const rvalues cannot bind to T&&.

In his notes An overview of the new C++ (C++11), Scott Meyers gives precisely the same example from his old book, and concludes that it is now considered poor design to add the const return value. The recommended signature is now

Rational operator*(const Rational& lhs, const Rational& rhs);

UPDATE: As implied by @JohannesSchaub-litb in the comments, in C++11 you can also use a reference qualifier on the assignment operator so that it will only accept lvalues as its left argument (i.e. the *this pointer, which is why this feature is also known as "rvalue references for *this"). You'll need g++ >= 4.8.1 (just released) or Clang >= 2.9 to make use of it.

Does const help the optimizer? C++

const does not help the optimizer.

Since const can be cast away with const_cast, it's possible to write programs that use const in a number of places, then cast it away and modify variables anyway, with defined behavior according to the standard. The compiler therefore must look at the actual code of the program to determine which variables are modified when, and it's probably pretty good at this anyway (for example it might determine a non-const variable is invariant over a certain block of code and optimize accordingly).

If the compiler blindly treated const as a guarantee that something won't change, the optimizer would break some well-formed programs.

const is a compile-time feature to help programmers write correct code, by adding some compile-time constraints, and indicating a code contract (eg. 'I promise not to change this parameter'). It has nothing to do with optimization. While invariants are important to optimizers, this has nothing to do with the const keyword.

There is one exception: objects declared with const. These cannot be modified; even if they are via casting, the behavior is undefined. There's some subtlety here:

const int ci = 5;
const_cast<int&>(ci) = 5; // undefined behavior, original object declared const

int i = 5;
const int& ci2 = i; // cannot modify i through ci2, const reference
const_cast<int&>(ci2) = 5; // OK, original object not declared const

So when the compiler sees const int ci it probably does assume it will never, ever change, because modifying it is undefined behavior. However, chances are this isn't the bottleneck in your program, it's just a more sophisticated #define. Apart from that, const is weak - just a keyword for the type system.

Reference with constant modifier

The first is illegal. You cannot bind a non-const reference to a temporary.

The second is legal. It creates a temporary double, initialized to 66.6, and makes val a const reference to it.

The const promises not to change the value through the reference. C++ does not permit you to bind a non-const reference to a temporary because that's usually an error.

Flutter const with const constructors

Lint interpreter always will show you the best possible way to improvise your coding and performance optimization tips.

For ex: in your code, there are many widgets that are not going to rebuild. cause it's compile-time constants as they are not dependent on other dynamic properties.

Column(
children: [
Container(
margin: const EdgeInsets.only(left: 20, right: 20),
height: 50,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(
Radius.circular(30),
),
color: Colors.black,
),
child: const Center( // compile time constant widget
child: const Text( // compile time constant widget
'Create Account',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 19),
),
),
),
const SizedBox( // compile time constant widget
height: 20,
)

Let say, your Text widget value depends on some other variable x, instead of the static value "Create Account" Then you cannot add const keyword before your Text Widget as it's not compile-time constant value.

Even if you don't worry about this kind of lint suggestions, it's fine. But, for your long journey in the development will be very smoother if you take consideration of lint suggestions

Is it better to remove const in front of primitive types used as function parameters in the header?

For all types (not just primitives), the top level const qualifiers in the function declaration are ignored. So the following four all declare the same function:

void foo(int const i, int const j);
void foo(int i, int const j);
void foo(int const i, int j);
void foo(int i, int j);

The const qualifier isn't ignored inside the function body, however. There it can have impact on const correctness. But that is an implementation detail of the function. So the general consensus is this:

  1. Leave the const out of the declaration. It's just clutter, and doesn't affect how clients will call the function.

  2. Leave the const in the definition if you wish for the compiler to catch any accidental modification of the parameter.

Why are references to const necessary to avoid copying parameters

Yes, any kind of reference will do. Making it const makes it more flexible as it can accept const variables or temporaries as parameters, and documents (and enforces) your intent not to modify the parameter.

Dart,Flutter : Meaning of const modifier,Isn't Colors.yellow [200] a constant?

MaterialColor yellow is constant but not its underlying color map.

If you take a look inside the implementation of MaterialColor yellow,
you will find that its color map <int, Color>{...} is not const qualified.

static const MaterialColor yellow = MaterialColor(
_yellowPrimaryValue,
<int, Color>{
50: Color(0xFFFFFDE7),
100: Color(0xFFFFF9C4),
200: Color(0xFFFFF59D),
300: Color(0xFFFFF176),
400: Color(0xFFFFEE58),
500: Color(_yellowPrimaryValue),
600: Color(0xFFFDD835),
700: Color(0xFFFBC02D),
800: Color(0xFFF9A825),
900: Color(0xFFF57F17),
});

Why is const-correctness specific to C++?

Well, it will have taken me 6 years to really understand, but now I can finally answer my own question.

The reason C++ has "const-correctness" and that Java, C#, etc. don't, is that C++ only supports value types, and these other languages only support or at least default to reference types.

Let's see how C#, a language that defaults to reference types, deals with immutability when value types are involved. Let's say you have a mutable value type, and another type that has a readonly field of that type:

struct Vector {
public int X { get; private set; }
public int Y { get; private set; }
public void Add(int x, int y) {
X += x;
Y += y;
}
}

class Foo {
readonly Vector _v;
public void Add(int x, int y) => _v.Add(x, y);
public override string ToString() => $"{_v.X} {_v.Y}";
}

void Main()
{
var f = new Foo();
f.Add(3, 4);
Console.WriteLine(f);
}

What should this code do?

  1. fail to compile
  2. print "3, 4"
  3. print "0, 0"

The answer is #3. C# tries to honor your "readonly" keyword by invoking the method Add on a throw-away copy of the object. That's weird, yes, but what other options does it have? If it invokes the method on the original Vector, the object will change, violating the "readonly"-ness of the field. If it fails to compile, then readonly value type members are pretty useless, because you can't invoke any methods on them, out of fear they might change the object.

If only we could label which methods are safe to call on readonly instances... Wait, that's exactly what const methods are in C++!

C# doesn't bother with const methods because we don't use value types that much in C#; we just avoid mutable value types (and declare them "evil", see 1, 2).

Also, reference types don't suffer from this problem, because when you mark a reference type variable as readonly, what's readonly is the reference, not the object itself. That's very easy for the compiler to enforce, it can mark any assignment as a compilation error except at initialization. If all you use is reference types and all your fields and variables are readonly, you get immutability everywhere at little syntactic cost. F# works entirely like this. Java avoids the issue by just not supporting user-defined value types.

C++ doesn't have the concept of "reference types", only "value types" (in C#-lingo); some of these value types can be pointers or references, but like value types in C#, none of them own their storage. If C++ treated "const" on its types the way C# treats "readonly" on value types, it would be very confusing as the example above demonstrates, nevermind the nasty interaction with copy constructors.

So C++ doesn't create a throw-away copy, because that would create endless pain. It doesn't forbid you to call any methods on members either, because, well, the language wouldn't be very useful then. But it still wants to have some notion of "readonly" or "const-ness".

C++ attempts to find a middle way by making you label which methods are safe to call on const members, and then it trusts you to have been faithful and accurate in your labeling and calls methods on the original objects directly. This is not perfect - it's verbose, and you're allowed to violate const-ness as much as you please - but it's arguably better than all the other options.

Should I return const objects?

Top level cv-qualifiers on return types of non class type are ignored.
Which means that even if you write:

int const foo();

The return type is int. If the return type is a reference, of course,
the const is no longer top level, and the distinction between:

int& operator[]( int index );

and

int const& operator[]( int index ) const;

is significant. (Note too that in function declarations, like the above,
any top level cv-qualifiers are also ignored.)

The distinction is also relevant for return values of class type: if you
return T const, then the caller cannot call non-const functions on the
returned value, e.g.:

class Test
{
public:
void f();
void g() const;
};

Test ff();
Test const gg();

ff().f(); // legal
ff().g(); // legal
gg().f(); // **illegal**
gg().g(); // legal

Can const-correctness improve performance?

const correctness can't improve performance because const_cast and mutable are in the language, and allow code to conformingly break the rules. This gets even worse in C++11, where your const data may e.g. be a pointer to a std::atomic, meaning the compiler has to respect changes made by other threads.

That said, it is trivial for the compiler to look at the code it generates and determine if it actually writes to a given variable, and apply optimizations accordingly.

That all said, const correctness is a good thing with respect to maintainability. Otherwise, clients of your class could break that class's internal members. For instance, consider the standard std::string::c_str() -- if it couldn't return a const value, you'd be able to screw around with the internal buffer of the string!

Don't use const for performance reasons. Use it for maintainability reasons.



Related Topics



Leave a reply



Submit