在2016年奥卢ISO C++标准会议上,一项名为Inline Variables的提案被标准委员会投票选为C++ 17.
通俗地说,什么是内联变量,它们如何工作以及它们对什么有用?如何声明,定义和使用内联变量?
考虑以下内联函数:
// Inline specifier version
#include<iostream>
#include<cstdlib>
inline int f(const int x);
inline int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Run Code Online (Sandbox Code Playgroud)
和constexpr等效版本:
// Constexpr specifier version
#include<iostream>
#include<cstdlib>
constexpr int f(const int x);
constexpr int f(const int x)
{
return 2*x;
}
int main(int argc, char* argv[])
{
return f(std::atoi(argv[1]));
}
Run Code Online (Sandbox Code Playgroud)
我的问题是:说明constexpr符是否意味着说明inline符,如果一个非常量参数传递给一个constexpr函数,编译器将尝试inline该函数,就像说明inline符被放入其声明一样?
C++ 11标准能保证吗?
好吧,无论如何不是C/C++专家,但我认为头文件的目的是声明函数,然后C/CPP文件来定义实现.
但是,今晚回顾一些C++代码,我发现这是在类的头文件中...
public:
UInt32 GetNumberChannels() const { return _numberChannels; } // <-- Huh??
private:
UInt32 _numberChannels;
Run Code Online (Sandbox Code Playgroud)
那么为什么标题中有实现呢?是否与const关键字有关?这是内联类方法吗?与定义CPP文件中的实现相比,这样做的好处/意义究竟是什么?
是否可以声明一个变量extern constexpr并在另一个文件中定义它?
我试了但是编译器给出了错误:
constexpr变量'i'的声明不是定义
在.h:
extern constexpr int i;
Run Code Online (Sandbox Code Playgroud)
在.cpp中:
constexpr int i = 10;
Run Code Online (Sandbox Code Playgroud) 我想要一个带有非整数常量的头文件,例如一个类.注意常数也并不需要是一个编译时间常数.
static const std::string Ten = "10";
Run Code Online (Sandbox Code Playgroud)
这编译但不可取,因为每个编译单元现在都有自己的Ten副本.
const std::string Ten = "10";
Run Code Online (Sandbox Code Playgroud)
这将编译但会因为多重定义的Ten的链接器错误而失败.
constexpr std::string Ten = "10"s;
Run Code Online (Sandbox Code Playgroud)
这可以工作,但前提是字符串构造函数也是constexpr.它会但是我不能指望每个非整数常量都有一个constexpr构造函数......或者我可以吗?
extern const std::string Ten = "10";
Run Code Online (Sandbox Code Playgroud)
这似乎有效,但我担心如果我错误地呼吸,我会收到链接器错误.
inline const std::string Ten( ) { return "10"; }
Run Code Online (Sandbox Code Playgroud)
这有我想要的一切,除了干净的语法.另外,现在我必须将常量称为函数调用Ten().
inline const std::string = "10";
Run Code Online (Sandbox Code Playgroud)
这似乎是理想的解决方案.当然inline,标准不允许变量.
我想在API中提供一个字符串常量,如下所示:
extern const char* const SOME_CONSTANT;
Run Code Online (Sandbox Code Playgroud)
但是,如果我在我的静态库源文件中定义它
const char* const SOME_CONSTANT = "test";
Run Code Online (Sandbox Code Playgroud)
我在链接到该库并使用SOME_CONSTANT时遇到链接器错误:
错误1错误LNK2001:未解析的外部符号"char const*const SOME_CONSTANT"(?SOME_CONSTANT @@ 3QBDB)
从extern const char* const声明和定义中删除指针const-ness(第二个const关键字)使其工作.如何使用指针常量导出它?
我有一个名为abc.h的头文件,其中我想用外部链接定义一个常量.因此它包含声明
--------------- abc.h -------------------------
extern const int ONE = 1;
Run Code Online (Sandbox Code Playgroud)
接下来,我有main.cpp,我想使用ONE的值.因此我在使用它之前在main.cpp中声明了ONE
--------------- main.cpp中---------------------
extern const int ONE;
int main()
{
cout << ONE << endl;
}
Run Code Online (Sandbox Code Playgroud)
我收到错误"ONE的多个定义".
我的问题是,如何使用外部链接声明一个const,并在随后的不同文件中使用它,这样常量只有一个内存位置,而不是每个包含常量静态版本的文件.
我从main.cpp中删除了#include"abc.h",一切正常.
g ++ abc.h main.cpp -o main
ONE的地址在标题和主要内容中相同.所以它有效.
但我不明白编译器如何在main.cpp中解析ONE而不包含include语句的定义
似乎g ++做了一些魔术.这是一个不好的做法,main.cpp的读者不知道ONE声明在哪里,因为main.cpp中没有包含"abc.h"?
在我的项目中,我有很多枚举,需要有与枚举成员相关的其他属性和与枚举类型相关的辅助静态方法.
据我所知,这对于标准枚举类MyItem {...}是不可能的,所以对于我项目中的每个枚举类,我有一个辅助类MyItemEnum,它封装了这些辅助静态方法,并且还实例化了辅助实例本身,以便我可以访问他们的方法,以获得其他属性.
Bellow一个例子(尽可能简化,但我相信所讨论的所有功能都在那里).
MyItem.h
enum class MyItem : unsigned int {
Item1 = 1,
Item2 = 5
};
class MyItemEnum {
private:
MyItem myItem;
size_t extInfo;
MyItemEnum(const MyItem& myItem, size_t extInfo);
~MyItemEnum();
public:
static MyItemEnum Item1;
static MyItemEnum Item2;
static const MyItemEnum &get(MyItem myItem);
operator MyItem() const;
size_t getExt() const;
bool hasNext() const;
MyItem next() const;
};
Run Code Online (Sandbox Code Playgroud)
我认为意思是显而易见的,我不需要在这里提供.cpp部分...当我需要访问扩展功能时,我使用MyItem作为参数在接口和MyItemEnum中传递.
我的第一个问题是,上面的方法是否正常,或者我应该考虑一些完全不同的东西?
我的第二个问题涉及我使用constexpr尝试做的这个枚举的优化:
enum class MyItem : unsigned int {
Item1 = 1,
Item2 = 5
};
class MyItemEnum {
private:
MyItem …Run Code Online (Sandbox Code Playgroud) 因此,我知道在C ++中,如果静态成员是const文字类型,则可以在类内部对其进行初始化,如下所示:
class test{
public:
static constexpr int stc = 1;
private:
int a = 0;
int b = 0;
int c = 0;
};
Run Code Online (Sandbox Code Playgroud)
静态constexpr变量stc可以用在编译器可以直接替换成员值的地方,即
int main () {int array[test::stc];}
Run Code Online (Sandbox Code Playgroud)
但是,如果在不能由编译器直接替换值的上下文中使用:
int main() { const int &cs = test::stc; }
Run Code Online (Sandbox Code Playgroud)
然后编译器(c)生成一个错误
c++ -std=c++11 -pedantic t.cpp -o t
Undefined symbols for architecture x86_64:
"test::stc", referenced from:
_main in t-a8ee2a.o
ld: symbol(s) not found for architecture x86_64
Run Code Online (Sandbox Code Playgroud)
除非静态成员是在类外部定义的,例如:
constexpr int test::stc;
为什么会这样呢?
我正在使用GCC C为嵌入式产品开发硬件抽象库.在库中,有一个变量应该对链接库的应用程序是只读的,但可以在定义它的编译单元中进行修改.
是否有一种标准的,可接受的方式来声明允许应用程序读取变量中的值的整数(在库头文件中),但是如果尝试生成写回写的代码,则告诉编译器生成错误对吗?例如,如果我要将函数声明为:
extern void foo(int const bar);
Run Code Online (Sandbox Code Playgroud)
...然后允许调用者传递局部变量:
int bar = 0;
foo(bar);
Run Code Online (Sandbox Code Playgroud)
...但是如果函数声明尝试写入bar:
void foo(int const bar)
{
bar = 99;
}
Run Code Online (Sandbox Code Playgroud)
...然后编译器会报告错误:分配只读位置"bar".
放置const名称之前的语法似乎不会以与函数参数相同的方式应用于变量,并且下面的两行似乎实际上是等效的:
extern const int x;
extern int const y;
Run Code Online (Sandbox Code Playgroud)
...因为将y定义为int y;导致错误:'y'的冲突类型限定符,正如我所期望的那样,x被定义为int x;.
我知道我可以通过声明和定义一个返回值的访问器函数(它只能用作r值)来解决这个问题.
我在这里已经阅读了许多相关的问题,但是我找到的没有一个为C提供了明确的答案(而不是C++或C#):
有人可以指出我如何实现它的一个例子的方向,或者证实我怀疑它在语法上是不可实现的吗?