简体   繁体   English

使用constexpr而不仅仅是静态const变量还有什么呢?

[英]What more does using constexpr gives instead of just static const variables?

As I understand, calculation at compile time means, that at runtime instead of constexpr functions there will be const values (by definition, because they will be already calculated). 据我所知,在编译时计算意味着,在运行时而不是constexpr函数会有const值(根据定义,因为它们已经被计算)。 That touches functions (they already calculated, so, it is just as variable of function type), that touches variables (it is just as static const variable), same with classes. 触及函数(它们已经计算,因此,它只是函数类型的变量),它接触变量(它就像静态const变量一样),与类相同。

One plus from constexpr function I see: if in ANSI C, for example, I had to have 5 defines, maybe united logically, now I can write one such function and use it instead of 5 defines, being able to write logic to manipulate of set of constexpr function return values. 我从constexpr函数中得到一个加号:例如,如果在ANSI C中,我必须有5个定义,也许逻辑上是统一的,现在我可以编写一个这样的函数并使用它来代替5个定义,能够编写逻辑来操作constexpr函数返回值的集合。 So, as result I have same set of 5 values, but now I described them logically, writing such function. 所以,结果我有相同的5个值集,但现在我在逻辑上描述了它们,编写了这样的函数。

But I feel I understand something wrong, because I see such examples: 但我觉得我理解错了,因为我看到了这样的例子:

class vec3 {
        union {
                struct {
                        float _x, _y, _z;
                };
                float _v[3];
        };

public:
        constexpr vec3(): _x(0), _y(0), _z(0) {} // 
        constexpr vec3(float x, float y, float z): _x(x), _y(y), _z(z) {}(1)
        constexpr vec3(const vec3&) = default; // (2)
        vec3 &operator=(const vec3&) = default; // (3)
        constexpr float x() { return _x; } // (4)
        constexpr float y() { return _y; }
        constexpr float z() { return _z; }
        constexpr const float *v() { return _v; } // (5)
        float *v() { return _v; }
};

(1) I can understand if constructor without parameters is constexpr. (1)我可以理解没有参数的构造函数是否为constexpr。 Yes, it is some const state that can be calculated at compile time and use in future, maybe faster. 是的,它是一些const状态,可以在编译时计算并在将来使用,也许更快。 But why constructor with parameters? 但为什么构造函数有参数? Object body will be on Stack or on Heap, we don't know which parameters we will put there, what for is it? 对象体将在Stack或Heap上,我们不知道我们将放在哪个参数,它是什么?

(2, 3) Same here, what for is it? (2,3)同样在这里,它是什么? How can we calculate at compile time copying of unknown object? 我们怎样才能在编译时计算出未知对象的复制?

(4, 5) I wonder what for it can be used. (4,5)我想知道它可以用什么。 Just for object which state was calculated at compile time? 仅针对在编译时计算状态的对象? Or calling value of some object (that will be created at runtime) from Heap or Stack may costs much and that somehow will speed it on? 或者从Heap或Stack调用某个对象(将在运行时创建)的值可能会花费很多,而且会以某种方式加速它的速度?

You are missing the fact that the use of constexpr in member functions and constructors does not mean that they are always executed in compile-time. 您错过了在成员函数和构造函数中使用constexpr并不意味着它们总是在编译时执行的事实。 They are simply done so when possible. 它们只是在可能的情况下完成。

A few examples for clarity: 为清楚起见,举几个例子:

  constexpr vec3 myGlobalVec{1,2,3}; // uses vec3(x,y,z) in compile time
  constexpr vec3 copyOfGlobalVec = myGlobalVec; // uses copy constructor in compile time

  void foo(int n) {
      vec3 my(n,n,n); // uses the same constructor, but invoked in runtime
      // ...
  }

The same applies to the remaining constructors: the key point is that with constexpr -qualified functions and constructors, if the full arguments list contains constant expressions (and if the object at hand is a constant expression), then the result will also be a constant expression. 这同样适用于其余的构造函数:关键点是使用constexpr限定的函数和构造函数,如果完整的参数列表包含常量表达式(并且如果手头的对象是常量表达式),那么结果也将是一个常量表达。

The advantage of having constexpr getters is that attributes of constant expressions can be obtained for use in cases where only constant expressions are allowed. 使用constexpr getter的优点是可以获得常量表达式的属性,以便在只允许使用常量表达式的情况下使用。 A float cannot be used as a template parameter, but assuming the vector was made of int s, you could do this: float不能用作模板参数,但假设向量是由int的,你可以这样做:

  SomeClass<myGlobalVec.x()> anObject;

1: A constexpr constructor that takes parameters can be called at compile time if the parameters are known at compile time. 1:如果参数在编译时已知,则可以在编译时调用获取参数的constexpr构造函数。 This may be useful to encapsulate state, the same reason we use objects instead of primitive values at run time. 这可能对封装状态很有用,这与我们在运行时使用对象而不是原始值的原因相同。

2, 3: Similarly, one can copy a constexpr object at compile time if the original source object is also a compile-time value. 2,3:类似地,如果原始源对象也是编译时值,则可以在编译时复制constexpr对象。

4, 5: constexpr accessors can be called both at run time and at compile time. 4,5: constexpr访问器可以在运行时和编译时调用。 Run time performance is not directly relevant, except that constexpr methods are implicitly inline and otherwise well-behaved (not containing some undefined behavior) so may be more amenable to optimization. 运行时性能并不直接相关,除了constexpr方法隐式内联并且行为良好(不包含某些未定义的行为),因此可能更适合优化。

Object body will be on Stack or on Heap, (...) 对象体将在Stack或Heap上,(...)

This is at best irrelevant, and at worst wrong. 这至多是不相关的,最坏的是错误的。 In the C++ abstract machine the objects will be in some storage location. 在C ++抽象机器中,对象将位于某个存储位置。 In a real machine, the objects will be wherever the compiler deems appropriate, and that wherever may even be nowhere . 在真实的机器中,对象将在编译器认为合适的任何地方,并且在任何地方甚至可能无处

we don't know which parameters we will put there, what for is it? 我们不知道我们会把哪些参数放在那里,它是什么?

If we initialise an object using that constructor with constant expressions for arguments, the initialisation expression will also be a constant expression. 如果我们使用具有参数的常量表达式的构造函数初始化对象,则初始化表达式也将是常量表达式。 Constant expressions are special because they are the only kinds of expressions that can be used in certain particular contexts, like array sizes, or template arguments. 常量表达式是特殊的,因为它们是可以在某些特定上下文中使用的唯一种类的表达式,如数组大小或模板参数。 Other than counting as a constant expression there is no difference between this and a normal initialisation without constexpr . 除了作为常量表达式计数之外,没有constexpr ,这与正常初始化之间没有区别

How can we calculate at compile time copying of unknown object? 我们怎样才能在编译时计算出未知对象的复制?

The same as before: if we initialise a copy using a constant expression as the source, the copy will also be a constant expression. 与之前相同:如果我们使用常量表达式作为源初始化副本,则副本也将是常量表达式。 Note that constexpr is only about things counting as constant expressions or not. 请注意, constexpr只是关于计算为常量表达式的事物。 It isn't about when they are evaluated . 它不是关于何时进行评估

I wonder what for it can be used. 我想知道它可以用什么。 Just for object which state was calculated at compile time? 仅针对在编译时计算状态的对象?

See above :) The primary purpose is to allow use of those objects in contexts that require constant expressions. 见上文:)主要目的是允许在需要常量表达式的上下文中使用这些对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 静态const和constexpr变量有什么区别? - What is the difference between a static const and constexpr variable? 使用 constinit const 时 static_assert 失败。 constinit、constinit const、constexpr、const、非常量变量中的混淆 - static_assert fails while using constinit const. Confusion in constinit, constinit const, constexpr, const, nonconst variables 使用static,const,constexpr进行全局声明/初始化 - global declarations/initializations using static, const, constexpr constexpr const 与 constexpr 变量? - constexpr const vs constexpr variables? 为什么 constexpr const 作用域变量不是隐式 static? - Why aren't constexpr const scoped variables implicitly static? 有没有办法声明将使用 constexpr 在源文件中定义的公共 static const (有什么区别)? - Is there a way to declare a public static const that will be defined in the source file using constexpr (and what difference is there)? 变量上的`const constexpr`是多余的吗? - Is `const constexpr` on variables redundant? const vs constexpr 变量 - const vs constexpr on variables static,constexpr,const - 当它们一起使用时它们意味着什么? - static, constexpr, const - what do they mean when all used together? static constexpr 中的 constexpr 变量 function - static constexpr variables in a constexpr function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM