我通常认为preincrement比C++中的postincrement更有效.但是,当我最近阅读" 游戏引擎架构"(第二版)这本书时,有一节说,后增量优于for循环中的preincrement.因为,正如我引用的那样,"preincrement会在代码中引入数据依赖关系 - CPU必须等待增量操作完成才能在表达式中使用它的值." 这是真的?(这真的颠覆了我对这个问题的看法.)
以下是您感兴趣的部分的引用:
5.3.2.1增量前与增量后增量
请注意,在上面的示例中,我们使用的是C++的postincrement运算符
p++,而不是preincrement运算符++p.这是一个微妙但有时重要的优化.preincrement运算符在表达式中使用其(现在已修改的)值之前递增变量的内容.postincrement运算符在使用后递增变量的内容.这意味着写入会在代码中++p引入数据依赖关系 - CPU必须等待增量操作完成才能在表达式中使用其值.在深度流水线的CPU上,这引入了一个停顿.另一方面,p++没有数据依赖性.变量的值可以立即使用,增量操作可以在以后或与其使用并行进行.无论哪种方式,管道中都没有失速.当然,在
forloop(for(init_expr; test_expr; update_expr) { ... })的"update"表达式中,前后增量之间应该没有区别.这是因为任何好的编译器都会认识到没有使用变量的值update_expr.但是在使用该值的情况下,后增量是优越的,因为它不会在CPU的管道中引入停顿.因此,养成一直使用后增量的习惯是好的,除非你绝对需要preincrement的语义.
编辑:添加"上面的例子".
void processArray(int container[], int numElements)
{
int* pBegin = &container[0];
int* pEnd = &container[numElements];
for (int* p = pBegin; p != pEnd; p++)
{
int element = *p;
// process element...
}
}
void processList(std::list<int>& container)
{
std::list<int>::iterator pBegin = …Run Code Online (Sandbox Code Playgroud) 据我所知,堆栈上的多维数组将按行顺序占用连续内存.根据ISO C++标准使用指向元素的指针索引多维数组是不确定的行为?例如:
#include <iostream>
#include <type_traits>
int main() {
int a[5][4]{{1,2,3,4},{},{5,6,7,8}};
constexpr auto sz = sizeof(a) / sizeof(std::remove_all_extents<decltype(a)>::type);
int *p = &a[0][0];
int i = p[11]; // <-- here
p[19] = 20; // <-- here
for (int k = 0; k < sz; ++k)
std::cout << p[k] << ' '; // <-- and here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果指针没有超出数组的边界,上面的代码将编译并正确运行a.但这是否因为编译器定义的行为或语言标准而发生?ISO C++标准中的任何参考都是最好的.
除了使用指针之外,还有其他方法可以从函数返回接收对数组的引用吗?
这是我的代码.
int ia[] = {1, 2, 3};
decltype(ia) &foo() { // or, int (&foo())[3]
return ia;
}
int main() {
int *ip1 = foo(); // ok, and visit array by ip1[0] or *(ip1 + 0)
auto ip2 = foo(); // ok, the type of ip2 is int *
int ar[] = foo(); // error
int ar[3] = foo(); // error
return 0;
}
Run Code Online (Sandbox Code Playgroud)
和一个类版本.
class A {
public:
A() : ia{1, 2, 3} {}
int (&foo())[3]{ return ia; } …Run Code Online (Sandbox Code Playgroud) 这里发生了什么事?
#include <iostream>
using namespace std;
int main(){
int x=0,y=0;
true? ++x, ++y : --x, --y;
cout << "x: " << x << endl;
cout << "y: " << y << endl; //why does y=0 here?
x=0,y=0;
false ? ++x, ++y : --x, --y;
cout << "x: " << x << endl;
cout << "y: " << y << endl;
}
x: 1
y: 0
x: -1
y: -1
Run Code Online (Sandbox Code Playgroud)
第二种情况似乎很好.我希望x和y在第一种情况下增加到1,但只有左手操作数增加.
我对类数据成员的默认初始化感到困惑.这是示例代码.
#include <iostream>
#include <vector>
class A {
public:
int i;
A() {}
};
A a1;
A aa1[3];
std::vector<A> av1(3);
int main()
{
A a2;
A aa2[3];
std::vector<A> av2(3);
std::cout << a1.i << " " << a2.i << std::endl; // 0 undefined
std::cout << aa1[0].i << " " << aa2[0].i << std::endl; // 0 undefined
std::cout << av1[0].i << " " << av2[0].i << std::endl; // undefined undefined
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,只有a1.i和aa1[0~2].i被初始化为0,而其他的是未初始化的.我不知道为什么会这样.
具体来说,我已经知道的是(来自"C++ Primer"):
初始化过程是:
a1并且a2 …我很好奇许多字符串连接的性能.在C++中阅读了Efficient string concatenation之后,我做了一些测试.但结果因编译器不同而不同.
这是我的代码.(代码中的计时器来自此处.)
#include <iostream>
#include <sstream>
#include <string>
#include <chrono>
template<typename TimeT = std::chrono::milliseconds>
struct measure {
template<typename F, typename ...Args>
static typename TimeT::rep execution(F&& func, Args&&... args) {
auto start = std::chrono::system_clock::now();
std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
auto duration = std::chrono::duration_cast< TimeT>
(std::chrono::system_clock::now() - start);
return duration.count();
}
};
std::string strAppend(const std::string &s, int cnt) {
std::string str;
for (int i = 0; i < cnt; ++i)
str.append(s);
return str;
}
std::string strOp(const std::string &s, …Run Code Online (Sandbox Code Playgroud) 我的问题是为什么我不能通过指向基类的指针在派生类中调用受保护的虚拟成员函数,除非将派生类声明为基类的朋友?
例如:
#include <iostream>
class A {
friend class C; // (1)
protected:
virtual void foo() const = 0;
};
class B : public A {
void foo() const override { std::cout << "B::foo" << std::endl; }
};
class C : public A {
friend void bar(const C &);
public:
C(A *aa) : a(aa) { }
private:
void foo() const override {
a->foo(); // (2) Compile Error if we comment out (1)
//this->foo(); // (3) Compile OK, but this is …Run Code Online (Sandbox Code Playgroud) 这是示例:
template <int n>
class A { };
class B {
public:
int foo() {
return a.n; // error
}
private:
A<10> a;
};
Run Code Online (Sandbox Code Playgroud)
我想获得除模板本身以外的类中实例化类A<10>的非类型模板参数的值,有没有办法做到这一点?还是应该使用其他设计来避免此问题?BA