我正在阅读inline关于isocpp FAQ的这个问题,代码是给出的
void f()
{
int x = /*...*/;
int y = /*...*/;
int z = /*...*/;
// ...code that uses x, y and z...
g(x, y, z);
// ...more code that uses x, y and z...
}
Run Code Online (Sandbox Code Playgroud)
然后它说
假设一个典型的C++实现具有寄存器和堆栈,寄存器和参数在调用之前就被写入堆栈
g(),然后从堆栈内部g()读取参数 并再次读取以在g()返回时 恢复寄存器f().但是,这是一个很多不必要的阅读和写作的,尤其是当编译器能够使用寄存器变量的情况下x,y和z:每个变量可以被写入两次(如寄存器,也可以作为一个参数)和出两次(在使用时g()和在返回期间恢复寄存器f()).
我很难理解上面的段落.我尝试列出我的问题如下:
f()函数的功能与g(x, y, z)函数相同.x, y, z在调用之前如何进入g()寄存器,传入的参数g() …我正在阅读这个Stack Overflow问题,我在该问题的代码中添加了一个构造函数,如下所示,
class Foo {
struct Bar {
int i;
Bar(int a = 5) :i(a) {};
};
public:
Bar Baz() { return Bar(); }
};
int main() {
Foo f;
// Foo::Bar b = f.Baz(); // error
auto b = f.Baz(); // ok
std::cout <<"b.i="<< b.i<<endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
代码输出b.i=5.在那个问题中,它得出结论,私有的名称是不可访问的,但类型是.那么一般来说,类型和名称之间的区别是什么?
并说我有两个特定的场景.
以下两个声明之间的区别是什么?为什么我能得到的输出b.i=5从auto b = f.Baz();?
Foo::Bar b = f.Baz();
auto b = f.Baz();
Run Code Online (Sandbox Code Playgroud)如果我typedef Bar B;在公共部分添加,Foo以下有什么区别?
Foo::Bar b …Run Code Online (Sandbox Code Playgroud)我在isocpp FAQ上阅读这个问题,这个问题是解释如何编写返回类型???
template<class T, class U>
??? mul(T x, U y)
{
return x*y;
}
Run Code Online (Sandbox Code Playgroud)
我理解简单的方法是写auto mul(T x, U y) -> decltype(x*y),但问题也提供另一种方式,即替换???为decltype(*(T*)(0)**(U*)(0)).但是我不完全理解这decltype(*(T*)(0)**(U*)(0))是做什么的,它似乎是声明一个临时指针T*并将其初始化为零然后取消引用指针,然后乘以相同的类型对应U,我的理解是对的吗?
但为什么要使用指针?我认为decltype(T(0)*U(0))或decltype(T{0}*U{0})应该也有效.
在此Stack Overflow答案中 ,证明了C++中的别名可能会降低代码速度.并且C++中的别名不仅适用于指针,它也适用于引用,更一般地适用于标准指定的这些类型.特别是有
一种聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员)
所以根据我的理解,如果我有如下代码,
class A{
public:
int val;
};
void foo(vector<A> & array, int & size, A & a0) {
for(int i=0;i<size;++i) {
array[i].val = 2*a0.val;
}
}
Run Code Online (Sandbox Code Playgroud)
和可能的是,a0可以别名中的元素中的一个array,也可能是别名size由于上述引用的,所以a0和size必须装载对于每次迭代导致性能下降.
const &将无济于事,因为它不会避免标准规定的混叠.通过a0按值?但这会使a0我不喜欢的复制,因为在实践中,类A可能非常复杂,复制是一个非常昂贵的选择.在glibc中,malloc用arenas实现.因此,例如,由于线程A和B可能位于不同的场所,并且不同的场所保持不同的堆,并且线程A中的另一个调用不能使用线程A中首先分配的内存malloc和后来的内存.免费的记忆清单.freemalloc
谈到C++(也许是C++ 11,因为C++ 11有一个新标准),故事是否仍然相同?
或者不同的线程实际上共享相同的堆段和内存空闲列表,并且new在一个线程中可以先分配内存,new然后再delete由另一个线程分配d?
如果答案是依赖于实现的,那么问题是它们是如何在主要的C++编译器中实现的,例如g ++,MVC++,icc?
编辑
我认为这个问题在某种意义上是有效的,有时你会启动许多线程,并且在每个线程中你为大量对象动态分配/释放大量内存,并且你不希望你的应用程序使用内存高得离谱.
c++ multithreading memory-management dynamic-memory-allocation c++11
在Sutter在1:15:26的演讲中,它呈现了如下代码,
class employee{
std::string name_;
public:
template<class String, class=
std::enable_if_t< !std::is_same<std::decay_t<String>, std::string>::value > >
void set_name(String && name)
noexcept(std::isnothrow_assignable<std::string &, String>::value)
{
name_ = std::forward<String>(name);
}
}
Run Code Online (Sandbox Code Playgroud)
我知道std::forward如果name是左值,name_将如何工作,将得到复制构造; 如果name是右值,name_将构造移动.但是在幻灯片中它还说Optimized to steal from rvalues (and more),还有什么呢?
后来它表明这个代码似乎是所有四个实现中最快的,特别是因为char *,任何人都有耐心去理解这些代码并解释什么是更优化以及为什么它是最快的,特别是在这种情况下char *?
我在阅读文章时遇到了一个代码,作者声称"C++标准库提供了以下类型定义:"
namespace std {
namespace chrono {
typedef duration<signed int-type >= 64 bits,nano> nanoseconds;
typedef duration<signed int-type >= 55 bits,micro> microseconds;
typedef duration<signed int-type >= 45 bits,milli> milliseconds;
typedef duration<signed int-type >= 35 bits> seconds;
typedef duration<signed int-type >= 29 bits,ratio<60>> minutes;
typedef duration<signed int-type >= 23 bits,ratio<3600>> hours;
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是什么signed int-type >= 64 bits意思?这是否意味着signed int减去type?如果是这样,你怎么解释?
我正在阅读有关std::move移动构造函数和移动赋值运算符的内容.说实话,我现在得到的只是困惑.现在我有一节课:
class A{
public:
int key;
int value;
A(){key = 3; value = 4;}
//Simple move constructor
A(A&& B){ A.key = std::move(B.key);
A.value = std::move(B.value);}
};
Run Code Online (Sandbox Code Playgroud)
B是一个右值参考,为什么你可以申请std::moveravlue参考的成员?B.key和B.value已被移动,都已经失效,但如何B作为类的一个对象A被失效?A a(A()),A()显然是一个rvlaue,可以A()被移动std::move,为什么?同样,如果我有一个功能
int add(int && z){
int x = std:move(z);
int y = std:move(z);
return x+y;
}
如果我打电话add(5),怎么可以5移动,为什么?并且注意到z已经移动了两次,在z第一次移动之后,它已经失效,你怎么能再次移动它?
foo (T …我知道在c ++ 11中,移动语义已经在STL容器中实现,以避免临时对象.人们说,现在编写按价值返回的函数是完美的.但我有一些关于地球上实际可以避免多少次复制的混淆.请参阅以下示例:
vector<int> myVector() {
vector<int> res;
res.push_back(4);
res.push_back(5);
return res;
}
vector<int> v = myVector();
Run Code Online (Sandbox Code Playgroud)
我的理解是,在C++ 03,myVector返回的副本res(4,5复制一次),当评估vector<int> v = myVector(); vector<int>的拷贝构造函数vector<int>(const vector<int> &)被调用(4,5复制两次).然而,在C++ 11移动语义,我想知道的哪个副本4和5被避免?都?是否还调用了返回值优化以减少一次复制4和5?
我正在看Walter E. Brown的现代模板元编程.在54:40,给出如下代码
template<class T, T v>
struct integral_constant{
static constexpr T value = v;
constexpr operator T() const noexcept { return value; } // what does this mean?
constexpr T operator T() const noexcept { return value; }
};
Run Code Online (Sandbox Code Playgroud)
我的问题是这条线是什么意思
constexpr operator T() const noexcept { return value; },为什么没有返回类型但它仍在返回value?这是拼写错误吗?