I am learning about smart pointers and when trying to compile the following "stupid" code I get an error.
#include <memory>
#include <iostream>
class Test
{
std::string myString="dumm";
};
int main()
{
std::unique_ptr<Test> test(new Test());
std::cout<<test->myString<<std::endl;
return 0;
}
I just wanted to see, whether this works but I get :"Applying -> to std::unique_ptr instead of a pointer", which seems weird.
I am using c++ 11
Eit: The error is now fixed and I cancompile the above code. However, CLion still gives me "Cant apply -> to std::uniq_ptr"-stuff, which seems to be an error with the IDE
In a class the default visibility is private which makes the myString field invisible to the test object. Make it public:
#include <iostream>
#include <memory>
#include <string>
class Test {
public:
std::string myString = "dumm";
};
int main() {
std::unique_ptr<Test> test(new Test());
std::cout << test->myString;
}
Prefer std::make_unique to direct use of new if compiling for C++14 and later:
std::unique_ptr<Test> test = std::make_unique<Test>();
This function is not available in the C++11 standard which is what you are using.
Related
I'm getting the following error during compilation:
Severity Code Description Project File Line Suppression State
Error C2664 'mytest::Test::Test(const mytest::Test &)': cannot convert argument 1 from '_Ty' to 'const mytest::Test &' TotalTest C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\include\xutility 158
I have no idea what is, so I'm putting the code here to exemplify what was being done:
TotalTest.cpp
include <iostream>
#include "Test.h"
using namespace mytest;
int main()
{
std::cout << "Hello World!\n";
new Test();
}
Test.h
#pragma once
#include "Test.h"
#include <iostream>
namespace mytest
{
using namespace std;
class Test
{
public:
Test();
~Test();
shared_ptr<Test> t;
};
}
Test.cpp
#include "Test.h"
namespace mytest
{
Test::Test()
{
}
Test::~Test()
{
}
}
TestFactory.h
#pragma once
#include "Test.h"
#include <iostream>
namespace mytest
{
using namespace std;
class TestFactory
{
public:
TestFactory();
shared_ptr<Test> CreateTest(int testClass);
};
}
TestFactory.cpp
#include "TestFactory.h"
namespace mytest
{
TestFactory::TestFactory()
{
}
shared_ptr<Test> TestFactory::CreateTest(int testClass)
{
return make_shared<Test>(new Test());
}
}
I'm using Visual Studio C++ language standard: ISO C++14 Standard (/std:c++14)
In TestFactory::CreateTest(), make_shared<Test>(new Test()) is wrong, as Test does not have a constructor that accepts a Test* pointer as input.
You need to use make_shared<Test>() instead, letting make_shared() call the default Test() constructor for you:
shared_ptr<Test> TestFactory::CreateTest(int testClass)
{
return make_shared<Test>();
}
Any parameters you pass to make_shared() are passed to the constructor of the type specified in the template argument. In this case, there are no parameters needed.
The error comes from the following line:
return make_shared<Test>(new Test());
There are 2 ways of initializing a std::shared_ptr:
Using the std::shared_ptr constructor directly, which requires you to pass a Test object already allocated on the heap, e.g.:
std::shared_ptr<Test> p{ new Test() };
Using make_shared(), which performs the heap allocation internally, e.g.:
std::shared_ptr<Test> p{ std::make_shared<Test>() };
Where in the parentheses you can pass parameters to the constructor of Test.
The 2nd option is usually prefered. You can see more info here: Difference in make_shared and normal shared_ptr in C++
In addition:
Test.h should not include itself (it has #include "Test.h" at the top).
You should avoid using using namespace std;. More info here: Why is "using namespace std;" considered bad practice?
I have a piece of C++ code used std::tuple. I have enabled C++17 standard in both MSVC and g++. But it can only be built by g++.
As follows:
#include <future>
#include <utility>
#include <typeindex>
int main()
{
std::packaged_task<std::tuple<std::type_index, int>()> task{
[]() {return std::make_tuple(std::type_index(typeid(int)), 3); }
};
}
Error in MSVC:
Severity Code Description Project File Line Suppression State
Error C2512 'std::tuple::tuple': no appropriate default constructor available TestConsole C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.23.28105\include\future 213
I've also tried this, seems like it can't accept a type that don't have any default constructor:
#include <future>
#include <utility>
class Foo
{
public:
Foo() = delete;
Foo(int a) { a_ = a; }
int a_;
};
int main()
{
std::packaged_task<std::tuple<Foo, int>()> task{
[]() {return std::make_tuple(Foo(3), 3); }
};
}
I'm wondering what caused the problem and how can I solve it(or is there a better way?).
Any help will be really appreciated.
Edit: I've change int* into int. I don't think nullptr or int* is the point. It also can't be built. Thanks a lot.
Edit: I'm currently using Visual Studio 2019 (version 16.3.8)
I've been attempting to solve this problem for hours, because I can't get a pointer to delete itself so I created a text-based program for debugging. Why doesn't this work?
#include <iostream>
#include <memory>
#include <vector>
using namespace std;
class A {};
int main() {
vector<A> as;
std::auto_ptr<A> a(new A);
as.push_back(std::move(a));
return 0;
}
Considering the vector contains A objects, you want as.push_back(*a). You don't need std::move, the temporary *a is already moveable.
As a beginner programer, I can't seem to catch what is going astray here. I removed some code to show that the error results from this simple syntax:
main:
#include <iostream>
#include <vector>
using namespace std;
class Grader
{
public:
Grader( );
void addScore( int score )
{
vectorofints.push_back(score);
}
vector<int> vectorofints;
};
int main()
{
Grader g;
return 0;
}
You've declared a constructor for Grader so must provide an implementation. The easiest way to do this is to change
Grader( );
to
Grader( ) {}
Alternatively, if you just removed the declaration of the constructor, the compiler will generate it for you.
I've made a SSCE as best I can. My suspicion is that the shared pointers deconstruct (free) my objects before I ask for them in main. How can I prevent this without circumventing shared pointers altogether? This is in isolated problem in a program that otherwise is greatly helped by the use of shared_ptrs.
Test.h:
#ifndef TEST_H
#define TEST_H
#include <memory>
#include <iostream>
#include <vector>
class Test
{
public:
Test();
virtual ~Test();
static std::shared_ptr<Test> makeTestFrom(std::string l);
std::vector<std::shared_ptr<int>> reg_vec;
protected:
private:
};
#endif // TEST_H
Test.cpp
#include <memory>
#include <iostream>
#include <vector>
Test::Test():
reg_vec()
{
//ctor
}
Test::~Test()
{
//dtor
}
std::shared_ptr<Test> Test::makeTestFrom(std::string l)
{
std::shared_ptr<Test> sp(new Test());
std::shared_ptr<int> i(new int(3));
sp->reg_vec.push_back(i);
return sp;
}
main.cpp:
#include <memory>
#include <iostream>
#include <vector>
#include "include/Test.h"
using namespace std;
int main()
{
std::unique_ptr<Test> x(new Test());
x->makeTestFrom("loldoesntmatter");
std::cout << x->reg_vec[0] << std::endl;
return 0;
}
int main() {
std::unique_ptr<Test> x(new Test());
x->makeTestFrom("loldoesntmatter"); // you discarded the return
std::cout << x->reg_vec[0] << std::endl; // x->reg_vec is empty
return 0;
}
Also, too many shared pointers
You're making too many new objects. In main, you're looking for an int inside x->reg_vec, but makeTestFrom doesn't add anything to x, it creates a brand-new object and puts the integer inside that.
Besides that, you're abusing shared_ptr. In C++, avoid dynamic allocation when you can. int are cheaper to pass by value than with shared_ptr, so just use vector<int>. And Test objects can be created with automatic lifetime also.
Just because some other languages (i.e. Java) make everything a handle doesn't mean that's a good pattern for C++.