问题
I really can't find any use of it. My first idea was that I could use it to implement 'Design by Contract' without using macros like this:
struct S
{
S(constexpr int i) : S(i) { static_assert( i < 9, "i must be < 9" ); }
S(int i); //external defintion
char *pSomeMemory;
};
But this wouldn't compile. I thought we could also use it to reference same-variable without the need of additional memory to be created when we want to avoid the get/setters in order to make instances to one member from users to be read-only:
class S
{
private:
int _i;
public:
const int & constexpr i = _i;
};
But none of the above actually compiled. Can someone give me some insight why this keyword was being introduced?
回答1:
The goal of constexpr
depends on the context:
For objects it indicates that the object is immutable and shall be constructed at compile-time. Aside from moving operations to compile-time rather than doing them at run-time creating
constexpr
objects has the added advantage that they are initialize before any threads are created. As a result, their access never needs any synchronization. An example of declaring an object asconstexpr
would look like this:constexpr T value{args};
Obviously, for that to work,
args
need to be constant expressions.For functions it indicates that calling the function can result in a constant expression. Whether the result of
constexpr
function call results in a constant expression depends on the arguments and the definition of the function. The immediate implication is that the function has to beinline
(it will implicitly be made so). In addition, there are constraints on what can be done within such a function. For C++11 the function can have only one statement which, for non-constructors, has to be areturn
-statement. This restriction got relaxed in C++14. For example, the following is a definition of aconstexpr
function:constexpr int square(int value) { return value * value; }
When creating constexpr
object of non-built-in types the respective types will need a constexpr
constructor: the generated default constructor won't work. Obviously, a constexpr
constructor will need to initialize all members. A constexpr
constructor could look like this:
struct example {
int value;
constexpr example(int value): value(value) {}
};
int main() {
constexpr example size{17};
int array[size.value] = {};
}
The created constexpr
values can be used everywhere a constant expression is expected.
回答2:
The way I see it, constexpr
is a way to bring together the two C++ languages - the one that runs at runtime and the one that runs at compile time. Compile time programming is usually called meta-programming.
First there was C, with its macros. Macros were in fact little programs that were ran by the compiler. They had if statements (called #ifdef
), variables (with #define
). There's even an entire scripting language that runs in compile time.
When C++ came out, it had the C macros and nothing more. Then came the C++ templates. These introduced a different way of running compile-time code. The C++ meta-language was largely functional, allowing you to do loops with tail recursion, for example.
In C++ 11, they've decided that meta-programming can look better, so they've introduced constexpr
. Now you can write C++ functions that are also meta-functions. In C++ 14 it gets better, because the restrictions on constexpr functions have been relaxed.
回答3:
Here is a summary of points made by Alex Allain in his "Constexpr - Generalized Constant Expressions in C++11," which details the usefulness of constexpr
:
- First, with a
constexpr
specifier, the value of the function or variable can be at compile time. - Another benefit of the
constexpr
specifier is that it can replace macros with functions constexpr
will also benefit your template metaprogramming.
Benefit to efficiency:
constant expressions...allow certain computations to take place at compile time, literally while your code compiles rather than when the program itself is run. (Allain 2)
Performance benefit: if something can be done at compile time, it will be done once, rather than every time the program runs
Other benefits:
Such variables and functions can then be used where only compile time constant expressions are allowed. A constexpr specifier used in an object declaration implies const. A constexpr specifier used in an function declaration implies inline.(CPP 1)
Rules for constexpr
functions:
- It must consist of single return statement (with a few exceptions)
- It can call only other constexpr functions
- It can reference only constexpr global variables (Allain 6)
Rules for constexpr
constructors:
- each of its parameters must be literal type
- the class must have no virtual base classes
- the constructor must not have a function-try-block (CPP 6)
Citations
Allain, Alex, "Constexpr - Generalized Constant Expressions in C++11", Unspecified Date, "http://www.cprogramming.com/c++11/c++11-compile-time-processing-with-constexpr.html"
CPP, "Constexpr Specifier", 16 December 2014, http://en.cppreference.com/w/cpp/language/constexpr
EDIT: Sorry, It was my fault to make it seem like I was the author of these points, so I have corrected myself, changed various parts, and added citations to avoid plagiarism.
回答4:
Answer of " Can someone give me some insight why constexpr keyword was being introduced?"
Modern C++ supports two types of immutability.
1) const
2) constexpr.
constexper will be evaluated at the compile time. It is used to specify constness and allows placement of data in the memory where it might be corrupted.
Example 1:
void UseConstExpr(int temp)
{
// This code snippet is OK
constexpr int y = max + 300;
std::cout << y << std::endl;
// This code snippet gives compilation error
// [ expression must have a constant value]
constexpr int z = temp + 300;
}
Example 2:
int addVector(const std::vector<int>& inVect)
{
int sum = 0;
for ( auto& vec : inVect)
{
sum += vec;
}
std::cout << sum << std::endl;
return sum;
}
int main()
{
// vInt is not constant
std::vector<int> vInt = { 1,2,3,4,5,6 };
// This code snippet is OK
// because evaluated at run time
const int iResult = addVector(vInt);
// Compiler throws below error
// function call must have a constant value in a constant expression
// because addVector(vInt) function is not a constant expression
constexpr int iResult = addVector(vInt);
return 0;
}
Note: above source code are compiled on VS2015
来源:https://stackoverflow.com/questions/27473795/what-are-constexpr-useful-for