我想尝试一下我读到的关于在C++中按值返回的内容(它与在新对象中创建时传递值相同)我有这样的代码:
#include <iostream>
using namespace std;
class Kar{
public:
int n;
static int no;
Kar(){
n = ++Kar::no;
cout << "Creating Kar " << n << endl;
}
Kar(Kar &k){
n = ++Kar::no;
cout << "Copying Kar " <<k.n<< " to new Kar " << n << endl;
}
~Kar(){
cout << "Destroying Kar "<< n << endl;
}
Kar& operator= (const Kar &k);
};
Kar& Kar::operator= (const Kar &k){
cout << "Assigning Kar "<< k.n <<" to Kar "<< …Run Code Online (Sandbox Code Playgroud) 我正在阅读复制文章(以及它应该如何在C++ 17中得到保证),这让我有点困惑(我不确定我知道我以前认识的事情).所以这是一个最小的测试用例:
std::string nameof(int param)
{
switch (param)
{
case 1:
return "1"; // A
case 2:
return "2" // B
}
return std::string(); // C
}
Run Code Online (Sandbox Code Playgroud)
我看到它的方式,情况A和B对返回值执行直接构造,因此复制省略在这里没有意义,而案例C不能执行复制省略,因为有多个返回路径.这些假设是否正确?
另外,我想知道是否
std::string retval;总是返回一个或写入的情况下A,并B作为return string("1")等)"1"是暂时的,但我假设它被用作构造函数的参数std::stringreturn{},这会是一个更好的选择吗?)using namespace std;
Object returnObject(){
Object o;
return o; //place A
}
int main() {
Object CopiedO=returnObject();
return 0; //Place B
}
Run Code Online (Sandbox Code Playgroud)
对象定义是:
Object::Object() {
cout<<"Object::Object"<<endl;
}
Object::~Object() {
cout<<"Object::~Object"<<endl;
}
Object::Object(const Object& object) {
cout<<"Object::CopyObject"<<endl;
}
Run Code Online (Sandbox Code Playgroud)
结果是:
/*Object::Object
Object::~Object*/
Run Code Online (Sandbox Code Playgroud)
据我所知,o和CopiedO都将被解构,但为什么只有一次打印Object ::〜Object?
我认为没有内联,复制的o是o的副本.但是它不能打印Object :: CopyObject
一位同事编写了以下代码,我确信这是错误的.
我想向他解释问题,但不知道正确的术语,所以我找不到支持我的立场的参考资料:
他的代码:
BSTR someString = _bstr_t(L"Hello World");
Run Code Online (Sandbox Code Playgroud)
为什么我认为它是错误的:
我相信它会_bstr_t(L"Hello World");调用构造函数_bstr_t,并创建一个该类型的短期临时变量.在该行代码之后(在分号序列点之后),该临时符将被自动删除,并且其字符串空间被释放.
这将someString指向已释放的内存.
问题:
构造函数调用的正确术语是什么?
你能指出一些描述使用细节的参考/术语/页面吗?
临时_bstr_t对象有术语吗?
我想我会称之为"匿名,临时变量",但我不知道这在技术上是否准确.
(或者在我的分析中我可能完全错了......如果是的话,我很想知道)
为了澄清:
_bstr_t是一个C++类,Microsoft通常用它来包装它们的BSTR类型,所以它有构造函数/析构函数/运算符等.
BSTR是一个只有a的typedef WCHAR*,所以它没有任何逻辑.它只是一个愚蠢的指针.
为什么在运算符重载时返回允许的构造函数?
这是一个例子:
Complex Complex::operator*( const Complex &operand2 ) const
{
double Real = (real * operand2.real)-(imaginary * operand2.imaginary);
double Imaginary = ( real * operand2.imaginary)+(imaginary * operand2.real);
return Complex ( Real, Imaginary );
}
Run Code Online (Sandbox Code Playgroud)
它似乎是返回对象的构造函数而不是对象本身?什么回到那里?
这似乎更有意义:
Complex Complex::operator*( const Complex &operand2 ) const
{
double Real = (real * operand2.real)-(imaginary * operand2.imaginary);
double Imaginary = ( real * operand2.imaginary)+(imaginary * operand2.real);
Complex somenumber ( Real, Imaginary );
return somenumber;
}
Run Code Online (Sandbox Code Playgroud) #include <iostream>
using namespace std;
struct A {
A() { cout << "default" << endl; }
A(const A&) { cout << "copy" << endl; }
A(A&&) { cout << "move" << endl; }
};
int main() {
A a{};
auto aa = A{};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
该程序将打印default,default在MSVC2013.标准是否表示在左侧创建带有auto的对象,或者第二个版本,auto aa = A{};首先调用默认构造函数然后将tmp变量移动/复制到左侧?
我是 C++ 的新手,想知道是否有办法在函数中创建对象,然后返回该对象而不必将其复制到内存中。我知道原始本地对象超出范围,但我希望编译器可以优化它,使对象的副本只重用相同的内存地址。
int foo()
{
int bar = 5;
std::cout << &bar << std::endl;
return bar;
}
int main()
{
char a;
auto b = foo();
std::cout << &b << std::endl;
std::cin >> a;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这将返回不同的内存地址。既然bar的地址不再需要,而且b的大小总是一样的,那么有什么理由不能只使用相同的地址并省去复制的步骤呢?
对于一个简单的整数并不重要,但对于更大的对象,确保返回的对象不会被复制到内存中的首选方法是什么?
以下是一个好方法吗?
int & foo(int & bar)
{
std::cout << &bar << std::endl;
// do things with bar
return bar;
}
int main()
{
char a;
auto bar = 5;
auto & b = foo(bar);
std::cout << &b << std::endl;
std::cin …Run Code Online (Sandbox Code Playgroud) 我是编程新手.对不起,我的英语不好.我试图使用rvalue作为初始对象的初始化器.因此,根据代码,它将打印出使用的构造函数和赋值运算符.但结果是对象"what2"和"what3",那些不打印任何东西.这是代码:
#include <iostream>
using namespace std;
class X{
public:
int x;
X()= default;
X(int num):x{num}{}
X(const X& y){
x = y.x;
std::cout << "copy constructor" << std::endl;
std::cout << x << std::endl;
}
X& operator=(const X& d){
x = d.x;
std::cout << "copy assignment" << std::endl;
return *this;
}
X(X&& y){
x = y.x;
std::cout << "move constructor" << std::endl;
}
X& operator=(X&& b){
x = b.x;
std::cout << "move assignment" << std::endl;
return *this;
}
};
X operator +(const …Run Code Online (Sandbox Code Playgroud) 我最近对内存(de)分配感到困惑 std::vectors
让我们假设我得到了整数的正常向量:
std::vector<int> intv;当我push_back有时int它会随着时间而增长.当我离开函数的范围(即)时,它会被释放,而不需要额外的调用.
大.让我们举另一个例子:
struct foo_t{
std::string bar:
unsigned int derp;
}
void hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
}
Run Code Online (Sandbox Code Playgroud)
好的.当我调用hurr()vector创建时,会创建一个foo_t实例,实例将被填充并推送到向量.因此,当我离开函数时,向量将被释放,内容(此处为一个foo_t)也会被释放?
下一个例子:
struct foo_t{
std::string bar:
unsigned int derp;
}
std::vector<foo_t> hurr(){
std::vector<foo_t> foov;
foo_t foo;
foo.bar = "Sup?";
foo.derp = 1337;
foov.push_back(foo);
return foov;
}
Run Code Online (Sandbox Code Playgroud)
在我的理解中,向量及其内容存在于堆栈中,它最终被时间覆盖并且我返回的向量和其内容将是无用的.或者它实际上是否返回了带有其内容副本的向量副本(如果它不是POD,则需要内容数据类型的Copy-Constructor)?
显而易见的事情:
struct foo_t{
std::string bar:
unsigned int derp;
}
std::vector<foo_t*> hurr(){
std::vector<foo_t*> foov;
foo_t …Run Code Online (Sandbox Code Playgroud) 我希望从这个测试程序中看到命名返回值优化 (NRVO) 的复制省略,但它的输出是“地址不匹配!” 所以 NRVO 没有发生。为什么是这样?
// test.cpp
// Compile using:
// g++ -Wall -std=c++17 -o test test.cpp
#include <string>
#include <iostream>
void *addr = NULL;
class A
{
public:
int i;
int j;
#if 0
~A() {}
#endif
};
A fn()
{
A fn_a;
addr = &fn_a;
return fn_a;
}
int main()
{
A a = fn();
if (addr == &a)
std::cout << "Addresses match!\n";
else
std::cout << "Addresses do not match!\n";
}
Run Code Online (Sandbox Code Playgroud)
笔记:
如果通过启用#if上述定义析构函数,则 …