从N3337的[12.8] [11]:
非联合类X的隐式定义的复制/移动构造函数执行其基础和成员的成员复制/移动.[注意:忽略非静态数据成员的大括号或大小写.另请参见12.6.2中的示例.-end note]初始化顺序与用户定义构造函数中基数和成员的初始化顺序相同(见12.6.2).让我们
x为构造函数的任何参数,或者对于移动构造函数,x值指的是参数.以适合其类型的方式复制/移动每个基本或非静态数据成员:- 如果成员是一个数组,则使用x的相应子对象直接初始化每个元素;
- 如果成员m具有右值引用类型T &&,则直接初始化为
static_cast<T&&>(x.m);- 否则,用x的相应基数或成员直接初始化基数或成员.
这实际上是一个澄清,但我看不到在该子句中提到左值引用成员.由于它没有提到它们,默认情况下似乎说它们是隐式成员移动的一部分,但是以下方法不起作用;
int x = 5;
int& y = x;
int& z(std::move(y)); //error: invalid initialization of non-const reference of type 'int&' from an rvalue of type 'std::remove_reference<int&>::type {aka int}'
Run Code Online (Sandbox Code Playgroud)
因此,可以安全地假设默认的移动构造函数区分成员是一个引用而且只是这样做
int& z = y;
Run Code Online (Sandbox Code Playgroud)
没有电话std::move?
我道歉但我不明白为什么以下不起作用(gcc 4.8.1):
#include <string>
using namespace std;
template <typename T> struct A{
//A(): s("why") { } //fine
//string s{"what"}; //also fine
//A() = default; //(same error as below)
string s = "why?!"; //error: conversion from 'const char [6]' to non-scalar type 'std::string {aka std::basic_string<char>}' requested|
};
struct B{
string s = "why?!"; //all good
};
int main(){
A<int> a;
B b;
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,通过引入模板,我无法=用于字符串的类内初始化器s.内置类型工作,实际上我可以通过在默认构造函数中使用大括号或显式初始化来规避它.为什么要大惊小怪使用=?
我正在尝试编写一个基于数学向量的类:
template <unsigned N> class Vector{
public:
Vector() = default;
Vector(std::initializer_list<double> li) { *this = li;}
Vector& operator=(std::initializer_list<double>);
private:
std::array<double, N> x = {}
}
template <unsigned N> inline Vector<N>& Vector<N>::operator=(std::initializer_list<double> li){
if(N != li.size()) throw std::length_error("Attempt to initialise Vector with an initializer_list of different size.");
std::copy(li.begin(), li.end(), x.begin());
return *this;
}
Run Code Online (Sandbox Code Playgroud)
我希望能够编写这样的代码;
Vector<3> a = {1,2,3};
a = {3,5,1};
Run Code Online (Sandbox Code Playgroud)
用户期望编写这样的代码是很自然的,对吧?但是,如果我使用错误大小的初始化列表,我希望发生编译时错误std::array.
std::array<double, 3> a = {2,4,2,4} //compile time error
Vector<3> a = {3,5,1,5} //run-time error as …Run Code Online (Sandbox Code Playgroud) 我试图理解这个程序中引发的错误的一致性:
#include <iostream>
class A{
public:
void test();
int x = 10;
};
void A::test(){
std::cout << x << std::endl; //(1)
std::cout << A::x << std::endl; //(2)
int* p = &x;
//int* q = &A::x; //error: cannot convert 'int A::*' to 'int*' in initialization| //(3)
}
int main(){
const int A::* a = &A::x; //(4)
A b;
b.test();
}
Run Code Online (Sandbox Code Playgroud)
输出是10 10.我标记了该计划的4个点,但(3)是我最关心的问题:
x 通常从成员函数内部获取.x使用范围运算符获取对象的对象,x并返回对象的左值.A::x返回int(2)中的左值,为什么然后&A::x返回不是int*,而是返回int A::* …这是来自C++ Primer Chapter 16.2.3(问题16.41)的问题:
写一个sum的版本,其返回类型保证足够大以保存添加的结果.
我敢肯定,有可能是能得到这份工作做了一些默默无闻的STL功能,但在章的背景下,推出标准型转换模板,如remove_reference<T>和make_signed<T>我敢肯定,它打算为我用它来做到这一点,与尾随返回类型一起使用.我能做的最好的事情是:
template <typename It> auto sum(It first, It second) -> typename make_unsigned<It>::type {
return first+second;
}
Run Code Online (Sandbox Code Playgroud)
这几乎回答了问题,但并不完全,它没有考虑到我可以传递两个unsigned ints的事实,这两个s加上超出了unsigned int可以容纳的值范围(因此循环回零).据我所知,转换模板无法帮助解决这个问题,是否有可能将返回类型推断为从传递的参数推导出的整数类型中的下一个最大整数类型?
我在 gnuplot 上生成等高线图并输出 eps 文件,然后我在乳胶中运行这些文件。这是四个等高线图,我需要它们都在我的页面的同一级别上。我很接近但是;

你可以看到剩下的三个图的空白占据了一些空间,如果它们被移除,它肯定会全部放在一条线上(所有图片都在同一水平上)。这是我的 gnuplot 代码的示例(对于那些没有 y 轴的代码);
reset
set size 0.38, 1
set terminal epslatex
set out 'finalpolar2.tex'
set termoption dash
#set title istitle;
set font "20"
unset xlabel
unset ylabel
set format y ""
set ylabel offset 1.5;
set palette model HSV rgbformulae 7,5,15
set contour;
set view map;
unset surface;
set cntrparam levels 8;
set isosamples 50;
unset key;
set size ratio 2
set xtics 0,0.5,40
set cbtics 0,0.02,40
set cbtics offset -1;
splot 'loop_final.txt' …Run Code Online (Sandbox Code Playgroud) 例如,我的一本书中的代码如下:
class HasPtr {
public:
HasPtr(const HasPtr& h): ps(new std::string(*h.ps)), i(h.i) { }
HasPtr(const std::string &s = std::string()): ps(new std::string(s)), i(0) { }
HasPtr& operator=(const HasPtr&);
~HasPtr() { delete ps; }
private:
std::string *ps;
int i;
};
HasPtr& HasPtr::operator=(const HasPtr &rhs){
auto newp = new string(*rhs.ps); // copy the underlying string
delete ps; // free the old memory
ps = newp; // copy data from rhs into this object
i = rhs.i;
return *this; // return this object
}
Run Code Online (Sandbox Code Playgroud)
看起来像运营商的内部=可能只是: …
我发现很遗憾,与未使用的普通函数不同,仍然必须定义未使用的虚函数.我对在创建类对象时创建的隐式vtable和vpointer有所了解- 这有点回答了问题(必须定义函数以便可以定义指向虚函数的指针)但这会进一步推动我的查询仍然.
如果根本不可能调用虚函数,为什么需要为函数创建vtable条目?
class A{
virtual bool test() const;
};
int main(){
A a; //error: undefined reference to 'vtable for A'
}
Run Code Online (Sandbox Code Playgroud)
虽然我声明A::test()它从未在程序中使用但它仍然会引发错误.编译器是否可以不通过程序运行并且实现test()从未被调用 - 因此不需要vtable条目?或者这对编译器来说是不合理的事情?
从5.1.2开始
[19]与lambda表达式关联的闭包类型具有已删除(8.4.3)的默认构造函数和已删除的副本分配运算符。它具有一个隐式声明的副本构造函数(12.8),并且可能具有一个隐式声明的move构造函数(12.8)。[注意:复制/移动构造函数的隐式定义与其他任何隐式声明的复制/移动构造函数的隐式定义相同。—尾注]
我正在阅读C ++ Primer 14.8.1,它解释了Lambda表达式被编译器翻译成未命名类的未命名对象。如果删除默认构造函数,如何定义不包含lambda捕获的lambda函数对象?
auto g = [](){};
Run Code Online (Sandbox Code Playgroud)
这在概念上与...不同吗?
class lambdaClass{
public:
lambdaClass() = delete;
lambdaClass& operator=(const lambdaClass&) = delete;
void operator()(){ }
//copy/move constructor and destructor implicitly defined
};
auto g = lambdaClass(); //would be an error since default is deleted.
Run Code Online (Sandbox Code Playgroud)
如果有捕获,则将定义除默认构造函数以外的其他构造函数,并且可以初始化此类对象(只要传递了参数)就可以了。但是,如果没有捕获并且删除了默认构造函数,则在概念上似乎无法创建lambda类对象。
编辑:嗯,尽管这是C ++ Primer中描述的方式,但是lambda类根据其lambda捕获创建构造函数的概念是没有根据的(因为我在标准中找不到该引用),因为以下代码甚至无法正常工作尽管我希望它在概念上:
int sz = 2;
auto a = [sz](){ return sz;};
decltype(a) b(10); //compiler error
decltype(a) b = a; //all good though
Run Code Online (Sandbox Code Playgroud) 来自C++ Primer第5版(D继承自B)
如果D使用public或protected从B继承,则从D派生的类的成员函数和朋友可以使用derived-tobase转换.如果D从B私下继承,则此类代码可能不会使用转换.
这有什么理由,还是我打算以面值来表达它?似乎很明显为什么会这样,但它在一个例子中绊倒了我:
#include <iostream>
using namespace std;
class Base {
public:
int x = 2;
};
class Derived : protected Base { };
class DerivedAgain : public Derived {
friend void test();
};
void test() {
??? a;
Base* p = &a;
cout << p->x;
}
int main(){
test();
}
Run Code Online (Sandbox Code Playgroud)
我想了解派生到基础转换中test()成员的可访问性x.考虑到三种潜在???的a功能类型的案例test().
???是Base.x是公共成员Base.在这种情况下没有问题.???是DerivedAgain.在这种情况下,Derived-to-Base转换是有意义的,因为test()可以friend访问所有成员DerivedAgain …我正在尝试创建一个vector<string>与其迭代器类似的类和另一个类(仅作为C++ Primer的练习(对于那些感兴趣的人练习14.28)).迭代器类的工作原理是使用一个vector<string>::size_type成员(称为curr)来表示向量的索引.我不想粘贴整个作品,因为它很长,但在尝试为迭代器定义我自己的减法运算符时,我已达到某种程度的混乱.最终它应该像减去两个迭代器一样工作,并在必要时产生负值.我有这样定义的函数:
??? operator-(const iterator& lhs, const iterator& rhs){
return (lhs.curr - rhs.curr);
}
Run Code Online (Sandbox Code Playgroud)
或者,另一个版本的混乱;
#include <vector>
#include <string>
#include <iostream>
using namespace std;
int main(){
vector<string>::size_type x = 5, y = 3;
??? z = (y-x); //what should ??? be if I want -2?
cout << z;
}
Run Code Online (Sandbox Code Playgroud)
(y-x)-2但它当然是回绕到,4294967294因为它是一个32位无符号表达式,然后将其存储在z中.我无法弄清楚如何定义我的返回类型,以便如果rhs(y)在序列中比lhs(x)更远,则返回正确的负值(存储在z中).
我想vector<string>::difference_type可能会做那个技巧,但我发现它size_type代表一个32位无符号整数,而difference_type代表一个32位有符号整数,所以有一个错误的包含有符号整数,这是未定义的行为 - 即使在我的电脑上它产生正确的结果.我可以static_cast一切long long int并返回long long int,但我觉得这将是一个有点太野蛮强迫.
C++ Primer第5版在第16.3章(讨论函数模板重载的章节)结尾处有一小段建议:
在定义任何函数之前,声明重载集中的每个函数.这样您就不必担心编译器在看到您打算调用的函数之前是否会实例化一个调用.
那么这告诉我,在重载解析期间选择候选和可行函数时,编译器可能会实例化最终未选择的函数模板吗?我试着看看这是否真的会发生:
template<class> struct always_false : std::false_type {};
template <typename T> void test(T const &){
static_assert(always_false<T>::value, "If this fires, it is instantiated");
}
template <typename T> void test(T*) { }
int main(){
int *q = nullptr;
test(q); //test(T*) should be the best match
}
Run Code Online (Sandbox Code Playgroud)
如果test(T const &)以任何形式实例化该程序将抛出编译器错误,除了程序按预期编译正常.那么什么样的编译事故就是小费试图阻止我?什么时候它会在看到我试图调用的函数之前实例化一个函数?
您可以从Project Euler中识别出这一点.我正在尝试编写一个代码,以便从三位数字乘以找到最大的回文数.有cout << i << endl; 在for循环中指示我们在过程中的位置.如果您完全按原样运行该代码,那么我将获得答案,但如果我取出cout << i << endl; 然后我似乎得到零.
我不知道发生了什么,代码似乎工作取决于我是否包括cout来指示我在哪里......什么?
#include <iostream>
using namespace std;
bool palindromecheck(int x);
int main() {
int largest=0;
for (int i = 999; i > 0; i--) {
cout << i << endl;
for (int j = 999; j > 0; j--) {
if (palindromecheck(i*j) && i*j > largest) {
largest = i*j;
}
}
}
cout << "The largest palindrome made from multiplying two 3-digit numbers is " << largest << …Run Code Online (Sandbox Code Playgroud) c++ ×12
c++11 ×6
templates ×4
constructor ×2
default ×1
definition ×1
friend ×1
function ×1
gcc ×1
gnuplot ×1
inheritance ×1
lambda ×1
latex ×1
move ×1
overloading ×1
palindrome ×1
reference ×1
subtraction ×1
sum ×1
unsigned ×1
virtual ×1